Chapter 11: PID Control Basics
Lesson 1: Proportional Control and Its Limitations
This lesson introduces proportional (P) feedback as the simplest linear controller, derives closed-loop models for unity-feedback configurations, and analyzes how the proportional gain affects steady-state error, transient response, and stability. We emphasize rigorous transfer-function derivations and connect them to numerical implementations in Python, C++, Java, MATLAB/Simulink, and Wolfram Mathematica, with a focus on basic robotic and servo applications.
1. Conceptual Overview of Proportional Control
In a standard single-input–single-output (SISO) unity-feedback control loop, the proportional controller computes the control input \( u(t) \) as a scalar multiple of the error \( e(t) \) between the reference \( r(t) \) and the measured output \( y(t) \):
\[ e(t) = r(t) - y(t), \qquad u(t) = K_p\, e(t), \]
where \( K_p \) is the proportional gain. We typically assume \( K_p > 0 \), so that if the output is below the reference (positive error), the controller increases the actuator effort.
For an LTI plant with transfer function \( G(s) \), proportional control in a unity-feedback configuration yields a closed-loop linear system whose properties (stability, transient response, steady-state error) we can analyze using the tools from the previous chapters (transfer functions, time response, root locus, and steady-state error).
Proportional control alone is widely used in practice (e.g., simple speed or temperature controllers) and in robotics (e.g., joint position control with only a proportional gain). However, as we will show, pure P control has intrinsic limitations that motivate integral and derivative actions in later lessons.
2. Unity-Feedback Architecture with P Control
Consider a unity-feedback loop with plant transfer function \( G(s) \) and proportional controller \( C(s) = K_p \). The reference is \( R(s) \), the output \( Y(s) \), and the error \( E(s) \). The relations are
\[ E(s) = R(s) - Y(s), \qquad U(s) = C(s)E(s) = K_p E(s), \]
\[ Y(s) = G(s) U(s) = K_p G(s) E(s). \]
Eliminating \( E(s) \) gives the standard closed-loop transfer functions. First write
\[ E(s) = R(s) - Y(s) = R(s) - K_p G(s) E(s), \]
\[ E(s)\bigl(1 + K_p G(s)\bigr) = R(s), \qquad E(s) = \frac{R(s)}{1 + K_p G(s)}. \]
Hence the closed-loop transfer function from reference to output is
\[ T(s) \equiv \frac{Y(s)}{R(s)} = \frac{K_p G(s)}{1 + K_p G(s)}, \]
and the error transfer function is
\[ \frac{E(s)}{R(s)} = \frac{1}{1 + K_p G(s)}. \]
The characteristic equation governing closed-loop poles is
\[ 1 + K_p G(s) = 0. \]
This is exactly the equation whose roots are traced in the root locus of Chapter 9 as \( K_p \) varies. Proportional control thus moves the closed-loop poles along the root locus emanating from the open-loop poles of \( G(s) \).
flowchart TD
R["Reference r"] --> S["Summing node: e = r - y"]
Y["Measured output y"] --> S
S --> E["Error e"]
E --> C["P controller: u = Kp * e"]
C --> P["Plant G(s)"]
P --> Y
3. Steady-State Error with Proportional Control
We now derive the steady-state error for a standard unity-feedback system under proportional control. Consider a unit-step reference \( r(t) = 1 \) so that \( R(s) = \dfrac{1}{s} \). The error Laplace transform is
\[ E(s) = \frac{1}{s}\,\frac{1}{1 + K_p G(s)}. \]
Assuming the closed-loop system is asymptotically stable, the Final Value Theorem gives
\[ e_{\text{ss}} = \lim_{t → \infty} e(t) = \lim_{s → 0} s E(s) = \lim_{s → 0} \frac{1}{1 + K_p G(s)}. \]
For a type-0 system (no pure integrators in \( G(s) \)), the DC gain \( G(0) \) is finite. Then
\[ e_{\text{ss}} = \frac{1}{1 + K_p G(0)}. \]
This shows:
- Increasing \( K_p \) reduces the steady-state error, but cannot drive it to zero for finite \( K_p \) when \( G(0) \) is finite and nonzero.
- If the plant has an integrator, i.e. is type-1 with \( G(s) = \dfrac{G_1(s)}{s} \) and finite \( G_1(0) \), then \( G(0) = \infty \) formally, and the steady-state error to a step input is zero even with proportional control.
For a type-0 plant, we can explicitly see how the steady-state error depends on the proportional gain by differentiating:
\[ e_{\text{ss}}(K_p) = \frac{1}{1 + K_p G(0)}, \qquad \frac{d e_{\text{ss}}}{d K_p} = -\frac{G(0)}{\bigl(1 + K_p G(0)\bigr)^2} < 0 \quad \text{for } K_p > 0,\; G(0) > 0. \]
Thus, mathematically, the steady-state error is strictly decreasing with \( K_p \), but it never becomes exactly zero for a type-0 plant unless \( K_p → \infty \), which is not feasible due to stability and actuator constraints.
4. First-Order Plant with Proportional Control
Consider the standard first-order plant model
\[ G(s) = \frac{k}{\tau s + 1}, \qquad k > 0,\; \tau > 0, \]
representing, for example, a DC motor speed response or a first-order actuator in robotics. With proportional control \( C(s) = K_p \) in unity feedback, the closed-loop transfer function is
\[ T(s) = \frac{Y(s)}{R(s)} = \frac{K_p G(s)}{1 + K_p G(s)} = \frac{K_p k}{\tau s + 1 + K_p k}. \]
We can rewrite this in standard first-order form \( \dfrac{K_{\text{cl}}}{\tau_{\text{cl}} s + 1} \) by factoring the denominator:
\[ T(s) = \frac{K_p k}{1 + K_p k} \cdot \frac{1}{\dfrac{\tau}{1 + K_p k}\,s + 1} = K_{\text{cl}} \cdot \frac{1}{\tau_{\text{cl}} s + 1}, \]
\[ K_{\text{cl}} = \frac{K_p k}{1 + K_p k}, \qquad \tau_{\text{cl}} = \frac{\tau}{1 + K_p k}. \]
Thus, proportional control modifies both the static gain and the time constant of the closed-loop system:
- Steady-state gain: For a unit-step input, the steady-state output is \( y_{\text{ss}} = K_{\text{cl}} = \dfrac{K_p k}{1 + K_p k} \). The steady-state error is \( e_{\text{ss}} = 1 - y_{\text{ss}} = \dfrac{1}{1 + K_p k} \).
- Speed of response: The closed-loop time constant \( \tau_{\text{cl}} = \dfrac{\tau}{1 + K_p k} \) decreases as \( K_p \) increases. Hence, the response becomes faster.
The time-domain step response for a unit step \( r(t) = 1 \) is
\[ y(t) = K_{\text{cl}} \bigl(1 - e^{-t/\tau_{\text{cl}}}\bigr), \qquad t \ge 0. \]
Since the closed-loop pole is at
\[ s = -\frac{1 + K_p k}{\tau}, \]
it is always in the left half-plane for \( K_p \ge 0 \), \( k > 0 \), and \( \tau > 0 \), so the first-order system with P control remains asymptotically stable.
5. Second-Order Plant and Trade-Offs with \( K_p \)
For a standard second-order plant with natural frequency \( \omega_n \) and damping ratio \( \zeta \),
\[ G(s) = \frac{\omega_n^2}{s^2 + 2 \zeta \omega_n s + \omega_n^2}, \]
the closed-loop characteristic equation with proportional control \( C(s) = K_p \) in unity feedback is
\[ 1 + K_p G(s) = 0 \;\Longleftrightarrow\; s^2 + 2 \zeta \omega_n s + \omega_n^2 (1 + K_p) = 0. \]
We can interpret this as a new effective second-order system
\[ s^2 + 2 \zeta_{\text{cl}} \omega_{\text{n,cl}} s + \omega_{\text{n,cl}}^2 = 0 \]
by identifying coefficients:
\[ \omega_{\text{n,cl}}^2 = \omega_n^2 (1 + K_p) \quad\Rightarrow\quad \omega_{\text{n,cl}} = \omega_n \sqrt{1 + K_p}, \]
\[ 2 \zeta_{\text{cl}} \omega_{\text{n,cl}} = 2 \zeta \omega_n \quad\Rightarrow\quad \zeta_{\text{cl}} = \frac{\zeta \omega_n}{\omega_{\text{n,cl}}} = \frac{\zeta}{\sqrt{1 + K_p}}. \]
Thus proportional control:
- Increases the natural frequency: \( \omega_{\text{n,cl}} \) increases with \( K_p \), speeding up the dynamics.
- Reduces the damping ratio: \( \zeta_{\text{cl}} \) decreases as \( K_p \) increases, which tends to increase overshoot and oscillations.
For \( 0 < \zeta_{\text{cl}} < 1 \), the peak overshoot \( M_p \) in response to a unit step is
\[ M_p(K_p) = \exp\!\left( -\frac{\pi \zeta_{\text{cl}}}{\sqrt{1 - \zeta_{\text{cl}}^2}} \right), \qquad \zeta_{\text{cl}} = \frac{\zeta}{\sqrt{1 + K_p}}. \]
As \( K_p \) increases, \( \zeta_{\text{cl}} \) decreases, and \( M_p(K_p) \) increases. We therefore have a fundamental trade-off:
- Large \( K_p \) → fast response, small steady-state error, but large overshoot and oscillations.
- Small \( K_p \) → sluggish response, larger steady-state error, but small overshoot.
This trade-off is one of the core limitations of pure proportional control.
6. Fundamental Limitations of Pure Proportional Control
We summarize the main theoretical limitations of proportional-only control in the unity-feedback configuration.
6.1 Nonzero Steady-State Error for Type-0 Plants
For a type-0 plant with finite \( G(0) \), the step steady-state error is
\[ e_{\text{ss}} = \frac{1}{1 + K_p G(0)} \neq 0 \quad \text{for any finite } K_p. \]
Thus, proportional control alone cannot guarantee perfect tracking of constant references unless the plant already has sufficient integral dynamics (type-1 or higher).
6.2 Trade-Off Between Speed, Overshoot, and Stability Margins
As we saw for first- and second-order models, increasing \( K_p \) simultaneously:
- reduces steady-state error,
- reduces time constant / increases natural frequency,
- reduces damping ratio and increases overshoot.
For higher-order plants, large \( K_p \) can move some closed-loop poles towards or into the right half-plane, as seen from the root locus, leading to oscillatory or unstable behavior.
6.3 Disturbance Rejection and Sensitivity
Suppose an input disturbance \( d(t) \) enters additively at the plant input so that \( U(s) = K_p E(s) + D(s) \). A simple derivation shows that the transfer function from disturbance to output is
\[ \frac{Y(s)}{D(s)} = \frac{G(s)}{1 + K_p G(s)}. \]
Increasing \( K_p \) tends to reduce the effect of low-frequency disturbances (where \( |G(s)| \) is large), but again at the cost of reduced stability margins. Without integral action, rejection of constant disturbances remains imperfect for type-0 plants.
6.4 Actuator Saturation and Nonlinear Effects
If we physically saturate the actuator (e.g., motor voltage or torque limits), then for large errors or large \( K_p \) the control signal \( u(t) = K_p e(t) \) may exceed allowable bounds and be clipped. The resulting closed-loop system is no longer linear, and the analysis above (based on transfer functions) no longer strictly applies. Nevertheless, P control with appropriately chosen \( K_p \) can work satisfactorily in many low-precision applications.
flowchart TD
START["Start control loop"] --> READ["Read sensor output y"]
READ --> ERR["Compute error e = r - y"]
ERR --> CTRL["Compute control u = Kp * e"]
CTRL --> SAT["Apply actuator limits"]
SAT --> CMD["Send command to actuator"]
CMD --> WAIT["Wait sampling period dt"]
WAIT --> READ
7. Python Implementation for a First-Order Servo (Robotics-Oriented)
We now implement a simple proportional controller for a first-order plant in Python using explicit Euler integration. This type of model can approximate, for example, the speed control of a small robot wheel motor:
\[ \dot{y}(t) = -\frac{1}{\tau} y(t) + \frac{k}{\tau} u(t), \qquad u(t) = K_p \bigl(r - y(t)\bigr). \]
Here is a basic simulation code using NumPy and Matplotlib. In a
robotics context, the same computation would be performed inside a
real-time loop, e.g., in a ROS node using rclpy or
rclcpp, while reading encoder measurements and writing
motor commands.
import numpy as np
import matplotlib.pyplot as plt
# Plant parameters (e.g., normalized DC motor)
k = 1.0 # static gain
tau = 0.5 # time constant (s)
# P controller gain
Kp = 5.0
# Simulation parameters
dt = 0.001
t_final = 5.0
n_steps = int(t_final / dt)
# Reference (unit step)
r = 1.0
# State and logs
y = 0.0
u = 0.0
umax = 10.0 # actuator saturation (for realism)
t_list = [0.0]
y_list = [y]
u_list = [u]
t = 0.0
for k_step in range(n_steps):
# P control law
e = r - y
u = Kp * e
# simple saturation
u = max(min(u, umax), -umax)
# first-order plant dynamics (explicit Euler)
dy = (-1.0 / tau) * y + (k / tau) * u
y = y + dy * dt
t = t + dt
t_list.append(t)
y_list.append(y)
u_list.append(u)
# Plot results
plt.figure()
plt.plot(t_list, y_list, label="Output y(t)")
plt.axhline(r, linestyle="--", label="Reference r(t)")
plt.xlabel("Time [s]")
plt.ylabel("Output / Reference")
plt.legend()
plt.grid(True)
plt.figure()
plt.plot(t_list, u_list, label="Control input u(t)")
plt.xlabel("Time [s]")
plt.ylabel("Control input")
plt.legend()
plt.grid(True)
plt.show()
The Python control library (Python Control Systems Library)
can also be used to construct \( G(s) \), close the
loop with a gain Kp, and compute time responses directly,
but the above code makes the P-control law and plant dynamics explicit,
as in a low-level robotic controller.
8. C++ Implementation for a Robot Joint Position Loop
In C++, proportional control is typically implemented in a real-time
control loop. For instance, in many robotic systems (e.g., ROS
ros_control or ros2_control), a custom
controller class reads joint positions and sends actuator commands using
a P (or PID) law.
The following snippet shows a simple loop where the joint dynamics are approximated by a first-order system as before:
#include <iostream>
int main() {
// Plant parameters
double k = 1.0;
double tau = 0.3;
// Controller parameters
double Kp = 20.0;
double dt = 0.001;
double t_final = 2.0;
// Reference (desired joint position)
double r = 1.0;
// State and actuator
double y = 0.0; // joint position
double u = 0.0; // torque command
double umax = 50.0; // saturation
for (double t = 0.0; t < t_final; t += dt) {
// Proportional control law
double e = r - y;
u = Kp * e;
// Saturation
if (u > umax) u = umax;
if (u < -umax) u = -umax;
// First-order joint dynamics (very simplified)
double dy = (-1.0 / tau) * y + (k / tau) * u;
y += dy * dt;
// In a real robot, here we would write u to a motor driver
// and read y from an encoder instead of simulating.
}
std::cout << "Final joint position y = " << y << std::endl;
return 0;
}
In a ROS-based robotic controller, this logic would appear inside an update method using real sensor readings and actuator interfaces, but the core proportional control law remains \( u = K_p (r - y) \).
9. Java Implementation (e.g., FRC / Robotics Frameworks)
Java is commonly used in educational robotics (e.g., FIRST Robotics Competition). Many frameworks provide a PID controller class that can be used in a P-only mode by setting the integral and derivative gains to zero. The essential logic is again \( u = K_p (r - y) \).
Here is a minimal Java example that simulates P control in a periodic loop. It could be adapted to a motor control framework by replacing the simulated plant with actual motor and sensor APIs:
public class ProportionalControllerDemo {
public static void main(String[] args) {
double k = 1.0;
double tau = 0.4;
double Kp = 10.0;
double dt = 0.001;
double tFinal = 3.0;
double r = 1.0; // reference
double y = 0.0; // output
double u = 0.0; // command
double umax = 12.0;
int steps = (int) (tFinal / dt);
for (int i = 0; i < steps; i++) {
// Proportional control law
double e = r - y;
u = Kp * e;
// Saturation
if (u > umax) u = umax;
if (u < -umax) u = -umax;
// First-order plant dynamics
double dy = (-1.0 / tau) * y + (k / tau) * u;
y += dy * dt;
// In a real robot, write 'u' to the motor and read 'y' from an encoder
}
System.out.println("Final output y = " + y);
}
}
Robotics libraries such as WPILib for FRC include PID controller classes
that internally perform similar computations each control cycle, with
the user specifying Kp, Ki, and
Kd. In this lesson, we focus on the P-only case (Ki = 0, Kd = 0).
10. MATLAB/Simulink and Wolfram Mathematica Implementations
10.1 MATLAB Script and Simulink Interpretation
In MATLAB, we can define the plant transfer function, close the loop with a proportional gain, and compute the step response using the Control System Toolbox. The same structure can be implemented in Simulink using a Gain block and a Transfer Fcn block in a feedback loop.
% Plant parameters
k = 1;
tau = 0.5;
% Plant transfer function G(s) = k / (tau s + 1)
s = tf('s');
G = k / (tau*s + 1);
% Proportional controller C(s) = Kp
Kp = 5;
C = Kp;
% Closed-loop transfer function with unity feedback
T = feedback(C*G, 1); % T(s) = (C*G) / (1 + C*G)
% Step response
figure;
step(T);
grid on;
title('Closed-loop step response with proportional control');
% Steady-state value and error
[y_ss, t_out] = step(T, 10);
y_final = y_ss(end);
e_ss = 1 - y_final
In Simulink, one would place:
- a Step block for \( r(t) \),
- a Sum block forming \( e(t) = r(t) - y(t) \),
- a Gain block with value
Kp, - a Transfer Fcn block implementing \( G(s) \), and
- a feedback connection from the plant output to the Sum block.
10.2 Wolfram Mathematica Implementation
Wolfram Mathematica includes functions for symbolic and numerical analysis of control systems. Below is an example using a first-order plant and a proportional controller, obtaining the closed-loop transfer function and a step response plot.
(* Define Laplace variable and parameters *)
Clear[s, k, tau, Kp];
k = 1; tau = 0.5; Kp = 5;
(* Plant transfer function and closed-loop T(s) *)
G[s_] := k/(tau*s + 1);
T[s_] := (Kp*G[s])/(1 + Kp*G[s]);
(* Inverse Laplace transform for unit-step response *)
Y[t_] = InverseLaplaceTransform[T[s]/s, s, t];
(* Simplify and display y(t) *)
FullSimplify[Y[t]]
(* Plot the step response *)
Plot[Y[t], {t, 0, 5},
AxesLabel -> {"t", "y(t)"},
PlotLabel -> "Closed-loop step response with P control"]
This symbolic approach recovers the analytical form of the step response derived earlier and provides a direct visualization of the influence of \( K_p \) on the time-domain behavior.
11. Problems and Solutions
Problem 1 (First-Order Closed-Loop Response): Consider the plant \( G(s) = \dfrac{2}{\tau s + 1} \) with \( \tau = 0.5 \) and a proportional controller \( C(s) = K_p = 4 \). Derive the closed-loop transfer function \( T(s) = \dfrac{Y(s)}{R(s)} \) and compute the steady-state error to a unit-step input.
Solution:
We have
\[ G(s) = \frac{2}{0.5 s + 1}, \quad C(s) = 4. \]
The closed-loop transfer function is
\[ T(s) = \frac{C(s)G(s)}{1 + C(s)G(s)} = \frac{8}{0.5 s + 1 + 8} = \frac{8}{0.5 s + 9}. \]
This is a first-order system with steady-state gain \( K_{\text{cl}} = \dfrac{8}{9} \). For a unit-step input, the steady-state output is \( y_{\text{ss}} = \dfrac{8}{9} \), so the steady-state error is
\[ e_{\text{ss}} = 1 - y_{\text{ss}} = 1 - \frac{8}{9} = \frac{1}{9}. \]
Problem 2 (General Expression for Step Error of Type-0 Plants): Let \( G(s) \) be any stable type-0 plant with finite DC gain \( G(0) \), and consider unity feedback with a proportional controller \( C(s) = K_p \). Prove that the steady-state error for a unit-step input is \( e_{\text{ss}} = \dfrac{1}{1 + K_p G(0)} \).
Solution:
For a unit-step reference, \( R(s) = \dfrac{1}{s} \). In unity feedback, the error is
\[ E(s) = R(s) - Y(s) = R(s) - T(s)R(s) = \bigl(1 - T(s)\bigr) R(s). \]
Since \( T(s) = \dfrac{K_p G(s)}{1 + K_p G(s)} \), we have
\[ 1 - T(s) = \frac{1}{1 + K_p G(s)}, \]
\[ E(s) = \frac{1}{1 + K_p G(s)} \cdot \frac{1}{s}. \]
By the Final Value Theorem, assuming closed-loop stability,
\[ e_{\text{ss}} = \lim_{t → \infty} e(t) = \lim_{s → 0} s E(s) = \lim_{s → 0} \frac{1}{1 + K_p G(s)} = \frac{1}{1 + K_p G(0)}, \]
which proves the result.
Problem 3 (Effect of Proportional Gain on Damping Ratio): For the second-order plant \( G(s) = \dfrac{\omega_n^2}{s^2 + 2 \zeta \omega_n s + \omega_n^2} \) with proportional control \( C(s) = K_p \) in unity feedback, derive the closed-loop damping ratio \( \zeta_{\text{cl}} \) as a function of \( \zeta \) and \( K_p \).
Solution:
From Section 5, the closed-loop characteristic equation is
\[ s^2 + 2 \zeta \omega_n s + \omega_n^2 (1 + K_p) = 0. \]
We match this to the standard form \( s^2 + 2 \zeta_{\text{cl}} \omega_{\text{n,cl}} s + \omega_{\text{n,cl}}^2 = 0 \). From the constant term we obtain
\[ \omega_{\text{n,cl}}^2 = \omega_n^2 (1 + K_p) \quad\Rightarrow\quad \omega_{\text{n,cl}} = \omega_n \sqrt{1 + K_p}. \]
From the coefficient of \( s \),
\[ 2 \zeta_{\text{cl}} \omega_{\text{n,cl}} = 2 \zeta \omega_n \quad\Rightarrow\quad \zeta_{\text{cl}} = \frac{\zeta \omega_n}{\omega_{\text{n,cl}}} = \frac{\zeta}{\sqrt{1 + K_p}}, \]
which is the desired expression.
Problem 4 (Trade-Off Between Error and Overshoot): Consider a stable type-0 plant with DC gain \( G(0) = k \) and proportional controller \( K_p \). Assume that increasing \( K_p \) beyond a certain value significantly decreases the closed-loop damping ratio (as in the second-order case). Explain, using the formulas for steady-state error and damping ratio, why a designer cannot usually reduce both steady-state error and overshoot simultaneously by adjusting \( K_p \) alone.
Solution:
The steady-state error for a step input is
\[ e_{\text{ss}}(K_p) = \frac{1}{1 + K_p k}, \]
which is strictly decreasing in \( K_p \). Therefore, from the perspective of steady-state tracking, larger \( K_p \) is always beneficial.
However, for a dominant second-order behavior, the closed-loop damping ratio satisfies approximately
\[ \zeta_{\text{cl}}(K_p) \approx \frac{\zeta}{\sqrt{1 + K_p}}, \]
which is strictly decreasing in \( K_p \). Since the peak overshoot \( M_p \) increases as \( \zeta_{\text{cl}} \) decreases, we find that larger \( K_p \) simultaneously:
- reduces \( e_{\text{ss}}(K_p) \),
- increases \( M_p \) via reduced \( \zeta_{\text{cl}} \).
Therefore, with proportional control alone, we cannot generally obtain both very small steady-state error and small overshoot. This motivates the introduction of integral and derivative actions in subsequent lessons.
12. Summary
In this lesson we introduced proportional (P) control in the context of unity-feedback linear systems. Starting from the fundamental relations \( u(t) = K_p (r(t) - y(t)) \) and \( Y(s)/R(s) = K_p G(s) / (1 + K_p G(s)) \), we analyzed how the proportional gain affects closed-loop pole locations, steady-state error, and transient response.
For first-order plants, we obtained explicit formulas for the closed-loop time constant and static gain, and showed that proportional control reduces but does not eliminate steady-state error for type-0 plants. For second-order plants, we derived the dependence of effective natural frequency and damping ratio on \( K_p \), demonstrating the inherent trade-off between speed, overshoot, and stability margins.
Implementation-oriented examples in Python, C++, Java, MATLAB/Simulink, and Wolfram Mathematica highlighted how the abstract control law is realized in software loops commonly used in robotic and mechatronic systems. These limitations of proportional control motivate the introduction of integral and derivative actions, which will be developed rigorously in the next lessons of this chapter.
13. References
- Minorsky, N. (1922). Directional stability of automatically steered bodies. Journal of the American Society of Naval Engineers, 34(2), 280–309.
- Bode, H. W. (1945). Network Analysis and Feedback Amplifier Design. Van Nostrand.
- Ziegler, J. G., & Nichols, N. B. (1942). Optimum settings for automatic controllers. Transactions of the ASME, 64(11), 759–768.
- Åström, K. J. (1993). Limitations on control system performance. European Journal of Control, 1(1), 2–20.
- Åström, K. J., & Hägglund, T. (1995). PID Controllers: Theory, Design, and Tuning. Instrument Society of America.
- Middleton, R. H. (1991). Trade-offs in linear control system design. Automatica, 27(2), 281–292.
- Horowitz, I. M. (1963). Synthesis of Feedback Systems. Academic Press.
- Franklin, G. F., Powell, J. D., & Emami-Naeini, A. (2014). Feedback Control of Dynamic Systems, 7th ed., Pearson. (Chapters on P and PID control.)