Chapter 2: Actuator-Space and Joint-Space Control Basics

Lesson 2: PD / PID in Joint Space

This lesson develops joint-space proportional-derivative (PD) and proportional-integral-derivative (PID) controllers for robot manipulators at the level of individual joints. We start from joint-level models derived from manipulator dynamics, derive closed-loop error dynamics, connect gain choices to second–order performance specifications, prove stability for PD control, and analyze PID via Routh–Hurwitz criteria. Finally, we provide multi-language implementations (Python, C++, Java, MATLAB/Simulink, Wolfram Mathematica) suitable for integration into robotics software stacks.

1. Joint-Space Dynamics and Independent Joint Approximation

From the robotics dynamics course, you know that an \( n \)-DOF manipulator has dynamics

\[ \mathbf{M}(q)\ddot{q} + \mathbf{C}(q,\dot{q})\dot{q} + \mathbf{g}(q) + \mathbf{f}_v \dot{q} = \tau, \]

where \( q \in \mathbb{R}^n \) is the vector of joint positions, \( \mathbf{M}(q) \) is the symmetric positive-definite inertia matrix, \( \mathbf{C}(q,\dot{q})\dot{q} \) collects Coriolis/centrifugal terms, \( \mathbf{g}(q) \) the gravity vector, \( \mathbf{f}_v \) viscous friction coefficients, and \( \tau \in \mathbb{R}^n \) the vector of joint torques (or generalized actuator inputs).

For basic joint-space PD/PID design we often start from the independent joint approximation, obtained by:

  • linearizing around a nominal configuration \( q_0 \),
  • approximating \( \mathbf{M}(q_0) \) as constant and diagonal,
  • treating coupling, Coriolis and gravity as either small disturbances or slowly varying terms.

For each joint \( i \) we get a scalar second-order model

\[ J_i \ddot{q}_i + b_i \dot{q}_i = \tau_i + d_i(t), \]

with inertia \( J_i > 0 \), viscous friction \( b_i \ge 0 \), control input \( \tau_i \) and lumped disturbance \( d_i(t) \) (unmodeled couplings, gravity mismatch, etc.).

The control objective in joint space (from Lesson 1 of this chapter) is to make each joint track a desired trajectory \( q_{d,i}(t) \). Define the tracking error and its derivative:

\[ e_i(t) = q_{d,i}(t) - q_i(t), \qquad \dot{e}_i(t) = \dot{q}_{d,i}(t) - \dot{q}_i(t). \]

We will design feedback laws for \( \tau_i \) so that \( e_i(t) \to 0 \) with prescribed transient behavior.

flowchart TD
  Qd["Desired joint trajectory qd(t)"] --> SUM["Error e = qd - q"]
  Q["Measured joint position q(t)"] --> SUM
  SUM --> CTRL["Joint PD / PID controller"]
  CTRL --> TAU["Actuator command tau"]
  TAU --> PLANT["Joint dynamics J d2q + b dq = tau + d(t)"]
  PLANT --> Q
        

2. PD Joint-Space Tracking Law

The simplest stabilizing feedback for the approximate second-order joint model is a proportional-derivative (PD) controller:

\[ \tau_i = K_{p,i} e_i + K_{d,i} \dot{e}_i, \]

where \( K_{p,i} > 0 \) is the proportional gain and \( K_{d,i} \ge 0 \) the derivative gain. At the vector level:

\[ \tau = \mathbf{K}_p e + \mathbf{K}_d \dot{e}, \]

with diagonal positive-definite gain matrices \( \mathbf{K}_p = \operatorname{diag}(K_{p,1},\dots,K_{p,n}) \) and \( \mathbf{K}_d = \operatorname{diag}(K_{d,1},\dots,K_{d,n}) \).

Consider a single joint with dynamics \( J\ddot{q} + b\dot{q} = \tau \) and PD law \( \tau = K_p(q_d - q) + K_d(\dot{q}_d - \dot{q}) \). Assume for now that \( q_d \) is constant (set-point regulation) so that \( \dot{q}_d = \ddot{q}_d = 0 \). Then the error dynamics are:

\[ e = q_d - q,\quad \dot{e} = -\dot{q},\quad \ddot{e} = -\ddot{q}, \]

and substituting into the plant equation:

\[ J(-\ddot{e}) + b(-\dot{e}) = K_p e + K_d \dot{e} \;\Rightarrow\; J\ddot{e} + (b + K_d)\dot{e} + K_p e = 0. \]

Thus the closed-loop error dynamics are linear, time-invariant, and second order:

\[ \ddot{e} + \frac{b+K_d}{J}\dot{e} + \frac{K_p}{J} e = 0. \]

3. Mapping PD Gains to Second-Order Specs

You have already seen that canonical second-order systems are written as

\[ \ddot{e} + 2\zeta \omega_n \dot{e} + \omega_n^2 e = 0, \]

where \( \omega_n > 0 \) is the natural frequency and \( \zeta \ge 0 \) is the damping ratio. Comparing with the PD closed-loop error equation, we obtain the gain-to-specification mapping:

\[ \frac{b + K_d}{J} = 2\zeta \omega_n,\qquad \frac{K_p}{J} = \omega_n^2. \]

Solving for the gains yields

\[ K_p = J \omega_n^2,\qquad K_d = 2J\zeta \omega_n - b. \]

For typical joint servos, internal motor/friction damping \( b \) is small compared with \( 2J\zeta\omega_n \), so designers often approximate \( K_d \approx 2J\zeta\omega_n \).

Using standard relations between \( \zeta \), \( \omega_n \) and performance indices — overshoot, rise time, settling time — you can choose PD gains directly from a specification such as “no more than 10% overshoot and settling time shorter than 0.5 s”.

4. Lyapunov Stability of Joint-Space PD Control

Consider again the scalar closed-loop error system

\[ J\ddot{e} + (b+K_d)\dot{e} + K_p e = 0 \quad\Leftrightarrow\quad \ddot{e} = -\frac{b+K_d}{J}\dot{e} - \frac{K_p}{J} e. \]

Define the state vector \( x = \begin{bmatrix} e \\ \dot{e} \end{bmatrix} \) and consider the Lyapunov candidate

\[ V(x) = \frac{1}{2}J \dot{e}^2 + \frac{1}{2}K_p e^2. \]

Since \( J > 0 \) and \( K_p > 0 \), we have \( V(x) > 0 \) for \( x \neq 0 \) and \( V(0) = 0 \). Its time derivative along trajectories is

\[ \dot{V} = J \dot{e}\ddot{e} + K_p e\dot{e} = \dot{e}\bigl(J\ddot{e} + K_p e\bigr). \]

Using the closed-loop dynamics \( J\ddot{e} = -(b+K_d)\dot{e} - K_p e \), we obtain

\[ \dot{V} = \dot{e}\bigl(-(b+K_d)\dot{e}\bigr) = -(b+K_d)\dot{e}^2 \le 0 \]

whenever \( b+K_d \ge 0 \). Thus \( V \) is non-increasing and the origin \( (e,\dot{e}) = (0,0) \) is stable. Moreover, the largest invariant set contained in \( \{x : \dot{V}(x) = 0\} \) is just the origin (because \( \dot{V} = 0 \Rightarrow \dot{e} = 0 \Rightarrow \ddot{e} = -\frac{K_p}{J}e = 0 \Rightarrow e = 0 \)), so by LaSalle’s invariance principle the equilibrium is globally asymptotically stable.

For the vector case with diagonal \( \mathbf{J} \), \( \mathbf{K}_p \succ 0 \), \( \mathbf{K}_d \succeq 0 \), we choose

\[ V(e,\dot{e}) = \frac{1}{2} \dot{e}^\top \mathbf{J} \dot{e} + \frac{1}{2} e^\top \mathbf{K}_p e, \]

and obtain similarly

\[ \dot{V} = -\dot{e}^\top(\mathbf{B}+\mathbf{K}_d)\dot{e} \le 0, \]

where \( \mathbf{B} \succeq 0 \) collects viscous friction terms. The same LaSalle argument yields global asymptotic convergence of joint errors in the ideal independent-joint model.

5. PID Joint-Space Control and Routh–Hurwitz Conditions

PD controllers remove overshoot and shape transients, but in the presence of constant disturbances (e.g. unmodeled gravity, static friction) they may exhibit nonzero steady-state error. A standard remedy is to add an integral term:

\[ \tau_i = K_{p,i} e_i + K_{d,i} \dot{e}_i + K_{i,i} \int_0^t e_i(\sigma)\,d\sigma. \]

Let \( z_i(t) = \int_0^t e_i(\sigma)\,d\sigma \) be the integral state. For constant reference and the simple model \( J\ddot{q} + b\dot{q} = \tau \) (no disturbance), the closed-loop error dynamics become

\[ J\ddot{e} + (b+K_d)\dot{e} + K_p e + K_i z = 0,\qquad \dot{z} = e. \]

Taking Laplace transforms (with zero initial conditions) gives the characteristic polynomial of the error system:

\[ J s^3 + (b+K_d)s^2 + K_p s + K_i = 0. \]

Let \( a_3 = J \), \( a_2 = b+K_d \), \( a_1 = K_p \), \( a_0 = K_i \). The Routh–Hurwitz conditions for all roots to have negative real part are:

\[ a_3 > 0,\quad a_2 > 0,\quad a_1 > 0,\quad a_0 > 0,\quad a_2 a_1 > a_3 a_0. \]

Since \( a_3 = J > 0 \), the stability conditions become

\[ b+K_d > 0,\quad K_p > 0,\quad K_i > 0,\quad (b+K_d)K_p > J K_i. \]

In other words, once \( K_p \) and \( K_d \) have been chosen (e.g. from desired PD behavior), the integral gain must be sufficiently small:

\[ 0 < K_i < \frac{(b+K_d)K_p}{J}. \]

This explains a common practical rule: start from a well-tuned PD controller and then add a small integral gain, increasing it until steady-state error is removed but before oscillations appear.

For constant disturbances \( d \) added to the joint dynamics, the integral action guarantees zero steady-state error (in the ideal model) provided the closed-loop system remains stable. This can be verified using the final value theorem and noting that the closed-loop transfer function from disturbance to error has a factor \( s \) in the numerator due to the integrator.

6. Implementation Aspects (Discrete Time, Derivative Filtering)

Real robot controllers run at a finite sampling period \( T_s \) (e.g. 1 ms) and obtain joint positions from encoders. A practical discrete-time PD/PID controller for a single joint at time step \( k \) looks like:

  • Position error: \( e[k] = q_d[k] - q[k] \).
  • Derivative estimate: \( \dot{e}[k] \approx \frac{e[k] - e[k-1]}{T_s} \), usually filtered.
  • Integral state: \( z[k] = z[k-1] + T_s e[k] \), often with anti-windup limiting.

A popular filtered derivative uses a first-order low-pass filter:

\[ \dot{e}_{\text{f}}[k] = (1-\alpha)\dot{e}_{\text{f}}[k-1] + \alpha\frac{e[k] - e[k-1]}{T_s}, \qquad 0 < \alpha \le 1. \]

The torque command is then

\[ \tau[k] = K_p e[k] + K_d \dot{e}_{\text{f}}[k] + K_i z[k]. \]

In multi-DOF manipulators, the same logic is applied joint-by-joint with vector gains. At this stage we are not cancelling coupling terms; we simply rely on high feedback gains and relatively slow motion so that the independent-joint approximation is acceptable. More advanced model-based compensation is addressed in later chapters.

7. Python Implementation (with Robotics Context)

Python is commonly used for prototyping robot controllers. Libraries such as roboticstoolbox-python (Peter Corke), numpy and scipy are particularly useful. Below is a simple simulation of PD and PID control for a single joint with parameters \( J, b \).


import numpy as np

def simulate_joint_pid(
    q0, dq0,
    qd,
    Kp, Kd, Ki,
    J=1.0, b=0.0,
    dt=0.001, T=2.0,
    use_integral=True
):
    """
    Simulate scalar joint dynamics:
        J * ddq + b * dq = tau
    with PD or PID control.
    """
    N = int(T / dt)
    q = np.zeros(N)
    dq = np.zeros(N)
    e_hist = np.zeros(N)
    t = np.linspace(0.0, T, N)

    q[0] = q0
    dq[0] = dq0
    z = 0.0                # integral state
    e_prev = qd - q0
    de_f = 0.0             # filtered derivative
    alpha = 0.2            # derivative filter weight

    for k in range(1, N):
        # For this demo, desired position is constant qd
        e = qd - q[k-1]
        de = (e - e_prev) / dt
        de_f = (1.0 - alpha) * de_f + alpha * de

        if use_integral:
            z += e * dt

        tau = Kp * e + Kd * de_f + (Ki * z if use_integral else 0.0)

        # Joint dynamics: explicit Euler integration
        ddq = (tau - b * dq[k-1]) / J
        dq[k] = dq[k-1] + ddq * dt
        q[k] = q[k-1] + dq[k] * dt

        e_hist[k] = e
        e_prev = e

    return t, q, dq, e_hist

if __name__ == "__main__":
    # Example: J = 0.5, b = 0.05, desired position qd = 1 rad
    J = 0.5
    b = 0.05
    # Choose gains from a second-order specification
    zeta = 0.7
    omega_n = 6.0
    Kp = J * omega_n**2
    Kd = 2.0 * J * zeta * omega_n - b
    Ki = 5.0   # must satisfy Routh-Hurwitz constraint

    t, q, dq, e_hist = simulate_joint_pid(
        q0=0.0, dq0=0.0,
        qd=1.0,
        Kp=Kp, Kd=Kd, Ki=Ki,
        J=J, b=b,
        dt=0.001, T=2.0,
        use_integral=True
    )

    # Plotting (requires matplotlib)
    import matplotlib.pyplot as plt
    plt.figure()
    plt.plot(t, q, label="q(t)")
    plt.plot(t, np.ones_like(t), "--", label="qd")
    plt.xlabel("time [s]")
    plt.ylabel("position [rad]")
    plt.legend()
    plt.grid(True)
    plt.show()
      

In a full robotics software stack (e.g. ROS), the PD/PID law would be implemented inside a real-time control loop (for instance using ros_control), reading joint states from sensor_msgs/JointState and writing actuator commands to a hardware interface.

8. C++ Implementation (Typical for Real-Time Control)

C++ is widely used for low-level robot control, often within frameworks like ROS and ros_control or Orocos. The following snippet shows a minimal PD/PID joint controller suitable for embedding into a control loop with fixed sampling period \( T_s \).


struct JointPID
{
    double Kp{0.0};
    double Kd{0.0};
    double Ki{0.0};

    double integral{0.0};
    double e_prev{0.0};
    double de_f{0.0};   // filtered derivative
    double alpha{0.2};  // derivative filter

    double update(double q, double dq,
                  double qd, double dqd,
                  double dt)
    {
        // tracking error (position only; dqd often 0 for setpoints)
        double e = qd - q;
        double de = (e - e_prev) / dt;
        de_f = (1.0 - alpha) * de_f + alpha * de;

        integral += e * dt;

        // anti-windup (simple clamping)
        const double z_max = 10.0;
        if (integral > z_max) integral = z_max;
        if (integral < -z_max) integral = -z_max;

        double tau = Kp * e + Kd * de_f + Ki * integral;

        e_prev = e;
        return tau;
    }
};

// Example usage in a high-rate control loop
// (e.g. inside a ROS control plugin)
void controlLoopStep(double dt)
{
    static JointPID pid;
    // gains could be parameterized or tuned online
    pid.Kp = 10.0;
    pid.Kd = 1.5;
    pid.Ki = 2.0;

    double q   = readJointPosition();
    double dq  = readJointVelocity();
    double qd  = desiredJointPosition();
    double dqd = 0.0; // for a constant setpoint

    double tau = pid.update(q, dq, qd, dqd, dt);
    sendJointTorqueCommand(tau);
}
      

In practice, this structure would be integrated with a robotics library (e.g. ros_control) that handles timing, joint state interfaces, and safety limits (effort saturation, rate limiting).

9. Java Implementation

Java is less common at the lowest control level but appears in higher-level robot stacks (e.g. rosjava) and educational systems. Below is a simple joint PD/PID controller class.


public class JointPIDController {
    private double Kp;
    private double Kd;
    private double Ki;

    private double integral = 0.0;
    private double ePrev = 0.0;
    private double dFiltered = 0.0;
    private double alpha = 0.2; // derivative filter weight

    public JointPIDController(double Kp, double Kd, double Ki) {
        this.Kp = Kp;
        this.Kd = Kd;
        this.Ki = Ki;
    }

    public double update(double q, double dq,
                         double qd,
                         double dt) {
        double e = qd - q;
        double de = (e - ePrev) / dt;
        dFiltered = (1.0 - alpha) * dFiltered + alpha * de;

        integral += e * dt;

        // naive anti-windup
        double zMax = 10.0;
        if (integral > zMax) integral = zMax;
        if (integral < -zMax) integral = -zMax;

        double tau = Kp * e + Kd * dFiltered + Ki * integral;
        ePrev = e;
        return tau;
    }
}
      

Linear algebra libraries such as EJML or Apache Commons Math can be used to extend this scalar controller to vectorized multi-joint implementations.

10. MATLAB / Simulink Implementation

MATLAB is ubiquitous in robotics education. The following script simulates joint-space PD control using ode45. Simulink offers block-diagram equivalents using standard blocks (“Sum”, “Gain”, “Integrator”) for the same structure.


function joint_pd_demo()
    J = 0.5;
    b = 0.05;
    qd = 1.0;

    zeta = 0.7;
    omega_n = 6.0;
    Kp = J * omega_n^2;
    Kd = 2 * J * zeta * omega_n - b;

    x0 = [0.0; 0.0];  % [q; dq]
    tspan = [0 2];
    [t, x] = ode45(@(t, x) dynamics_pd(t, x, qd, J, b, Kp, Kd), tspan, x0);

    q = x(:, 1);
    figure;
    plot(t, q, "LineWidth", 1.5); hold on;
    plot(t, qd * ones(size(t)), "--", "LineWidth", 1.0);
    xlabel("time [s]");
    ylabel("joint position [rad]");
    legend("q(t)", "qd");
    grid on;
end

function dx = dynamics_pd(t, x, qd, J, b, Kp, Kd)
    q = x(1);
    dq = x(2);

    e = qd - q;
    de = -dq; % since qd is constant

    tau = Kp * e + Kd * de;

    ddq = (tau - b * dq) / J;
    dx = [dq; ddq];
end
      

In Simulink, a PID joint controller is created by feeding the error \( e = q_d - q \) into a built-in PID Controller block and connecting its output to a joint model block (for example, a second-order transfer function or a Simscape Multibody joint). The Robotics System Toolbox can be used to incorporate full manipulator models in the loop.

11. Wolfram Mathematica Implementation

Wolfram Mathematica is well suited for symbolic analysis and numerical simulation of controlled joint dynamics. The snippet below defines a PD-controlled joint and uses NDSolve to simulate it.


J = 0.5;
b = 0.05;
qd = 1.0;
zeta = 0.7;
omegaN = 6.0;
Kp = J * omegaN^2;
Kd = 2 J zeta omegaN - b;

eqns = {
  q''[t] == (Kp (qd - q[t]) + Kd (0 - q'[t]) - b q'[t]) / J,
  q[0] == 0,
  q'[0] == 0
};

sol = NDSolve[eqns, q, {t, 0, 2}][[1]];

Plot[{q[t] /. sol, qd}, {t, 0, 2},
  PlotLegends -> {"q(t)", "qd"},
  AxesLabel -> {"t", "position"},
  GridLines -> Automatic
]
      

Symbolic tools can also be used to derive the characteristic polynomial, verify Routh–Hurwitz conditions, and perform parametric sweeps over \( K_p, K_d, K_i \).

12. Problems and Solutions

Problem 1 (PD Gain Design from Specs). A revolute joint has approximate model \( J\ddot{q} + b\dot{q} = \tau \) with \( J = 2 \) and \( b = 1 \). Design PD gains so that the closed-loop error dynamics behave approximately like a second-order system with \( \omega_n = 4 \) rad/s and \( \zeta = 0.7 \).

Solution. Comparing with the normalized second-order model

\[ \ddot{e} + 2\zeta\omega_n \dot{e} + \omega_n^2 e = 0 \quad\text{and}\quad \ddot{e} + \frac{b+K_d}{J}\dot{e} + \frac{K_p}{J} e = 0, \]

we obtain

\[ \frac{b+K_d}{J} = 2\zeta\omega_n,\qquad \frac{K_p}{J} = \omega_n^2. \]

With \( J = 2 \), \( b = 1 \), \( \omega_n = 4 \), \( \zeta = 0.7 \):

\[ K_p = J\omega_n^2 = 2 \cdot 16 = 32, \]

\[ K_d = 2J\zeta\omega_n - b = 2 \cdot 2 \cdot 0.7 \cdot 4 - 1 = (11.2) - 1 = 10.2. \]

Thus, \( K_p = 32 \), \( K_d = 10.2 \) yields the desired second-order behavior (up to modeling approximations).

Problem 2 (PID Stability via Routh–Hurwitz). For the same joint as in Problem 1, consider adding an integral gain \( K_i \). The characteristic polynomial of the error dynamics is \( 2s^3 + (1+K_d)s^2 + K_p s + K_i = 0 \). Using the PD gains from Problem 1, determine the admissible range of \( K_i \) for stability.

Solution. From Problem 1, \( K_p = 32 \), \( K_d = 10.2 \). The coefficients are

\[ a_3 = 2,\quad a_2 = 1 + K_d = 11.2,\quad a_1 = 32,\quad a_0 = K_i. \]

Routh–Hurwitz for a cubic requires:

\[ a_3 > 0,\quad a_2 > 0,\quad a_1 > 0,\quad a_0 > 0,\quad a_2 a_1 > a_3 a_0. \]

The first three are satisfied automatically for positive \( K_i \). The last inequality gives

\[ (11.2)(32) > 2K_i \quad\Rightarrow\quad 358.4 > 2K_i \quad\Rightarrow\quad K_i < 179.2. \]

Together with \( K_i > 0 \), the admissible range is \( 0 < K_i < 179.2 \). In practice one usually chooses \( K_i \) much smaller (e.g. \( K_i \approx 5 \)) to avoid aggressive integral action.

Problem 3 (Zero Steady-State Error with Integral Action). Consider the joint model with a constant disturbance torque \( d \): \( J\ddot{q} + b\dot{q} = \tau + d \). Show that a stable PID controller with \( K_i > 0 \) yields zero steady-state tracking error for a constant desired position \( q_d \).

Solution. Let \( e = q_d - q \). The closed-loop (linearized) transfer function from disturbance to error has the form

\[ E(s) = G_{ed}(s) D(s) = \frac{N(s)}{J s^3 + (b+K_d)s^2 + K_p s + K_i} D(s), \]

where \( D(s) = \frac{d}{s} \) for a constant disturbance and \( N(s) \) is some polynomial. The final value theorem gives

\[ e_{\infty} = \lim_{t \to \infty} e(t) = \lim_{s \to 0} s E(s) = \lim_{s \to 0} s \frac{N(s)}{J s^3 + (b+K_d)s^2 + K_p s + K_i} \frac{d}{s}. \]

The factor \( s \) in the numerator from the final value theorem cancels the pole in \( D(s) \). Evaluating at \( s = 0 \) then yields \( e_{\infty} = 0 \) because the denominator is \( K_i \neq 0 \) and \( N(0) \) is finite. Thus a stable PID controller with \( K_i > 0 \) eliminates steady-state error to constant disturbances.

Problem 4 (Lyapunov Proof for Vector PD Control). Consider the vector independent-joint model \( \mathbf{J}\ddot{q} + \mathbf{B}\dot{q} = \tau \) with diagonal \( \mathbf{J} \succ 0 \), \( \mathbf{B} \succeq 0 \). Let \( e = q_d - q \) for constant \( q_d \), and use the PD law \( \tau = \mathbf{K}_p e + \mathbf{K}_d \dot{e} \) with diagonal \( \mathbf{K}_p \succ 0 \), \( \mathbf{K}_d \succeq 0 \). Prove global asymptotic stability of \( e = \dot{e} = 0 \).

Solution. The error dynamics are

\[ \mathbf{J}\ddot{e} + (\mathbf{B} + \mathbf{K}_d)\dot{e} + \mathbf{K}_p e = 0. \]

Consider the Lyapunov function

\[ V(e,\dot{e}) = \frac{1}{2}\dot{e}^\top \mathbf{J} \dot{e} + \frac{1}{2} e^\top \mathbf{K}_p e. \]

Since \( \mathbf{J} \succ 0 \) and \( \mathbf{K}_p \succ 0 \), we have \( V > 0 \) for \( (e,\dot{e}) \neq (0,0) \) and \( V(0,0) = 0 \). Differentiating along trajectories:

\[ \dot{V} = \dot{e}^\top \mathbf{J}\ddot{e} + e^\top \mathbf{K}_p \dot{e} = \dot{e}^\top (\mathbf{J}\ddot{e} + \mathbf{K}_p e). \]

Using the closed-loop dynamics \( \mathbf{J}\ddot{e} = -(\mathbf{B}+\mathbf{K}_d)\dot{e} - \mathbf{K}_p e \), we obtain

\[ \dot{V} = \dot{e}^\top (-(\mathbf{B}+\mathbf{K}_d)\dot{e}) = -\dot{e}^\top (\mathbf{B}+\mathbf{K}_d)\dot{e} \le 0, \]

since \( \mathbf{B}+\mathbf{K}_d \succeq 0 \). The set where \( \dot{V} = 0 \) is \( \{(e,\dot{e}) : \dot{e} = 0\} \). Restricted to this set, the dynamics reduce to \( \mathbf{K}_p e = 0 \), hence \( e = 0 \). Therefore the largest invariant set inside \( \{\dot{V} = 0\} \) is the origin, and LaSalle’s invariance principle implies global asymptotic stability of \( (e,\dot{e}) = (0,0) \).

flowchart TD
  A["Choose PD gains from omega_n, zeta"] --> B["Check positivity: Kp > 0, Kd + B >= 0"]
  B --> C["Define V = 0.5 dq' J dq + 0.5 e' Kp e"]
  C --> D["Compute Vdot = -dq' (B + Kd) dq <= 0"]
  D --> E["Apply LaSalle to conclude e,dq -> 0"]
      

13. Summary

In this lesson we moved from the full manipulator dynamics to an independent-joint approximation and derived PD and PID controllers directly in joint space. For PD control we established exact equivalence with a second-order linear system and used this to map between gains and classical performance specifications \( (\omega_n, \zeta) \). We then proved global asymptotic stability for vector PD control using a quadratic Lyapunov function. Extending to PID control, we obtained a cubic characteristic polynomial and used Routh–Hurwitz conditions to derive explicit inequalities on the integral gain ensuring stability. Finally, we illustrated implementation details in Python, C++, Java, MATLAB/Simulink and Wolfram Mathematica, emphasizing discrete-time realization, derivative filtering, and integral anti-windup. These joint-level PD/PID controllers form the baseline upon which more advanced model-based and task-space controllers will be built in subsequent chapters.

14. References

  1. Takegaki, M., & Arimoto, S. (1981). A new feedback method for dynamic control of manipulators. Journal of Dynamic Systems, Measurement, and Control, 103(2), 119–125.
  2. Kelly, R. (1990). A simple set-point robot controller design formula. IEEE Transactions on Robotics and Automation, 6(5), 692–697.
  3. Kelly, R. (1993). PD control with desired gravity compensation of robot manipulators: A review. International Journal of Robotics and Automation, 8(2), 101–110.
  4. Arimoto, S. (1996). On stability and robustness of PID feedback control for robot manipulators. Systems & Control Letters, 28(3), 163–171.
  5. Spong, M. W. (1987). On the robust control of robot manipulators. IEEE Transactions on Automatic Control, 32(7), 512–518.
  6. Slotine, J.-J. E., & Li, W. (1988). Adaptive manipulator control: A case study. IEEE Transactions on Automatic Control, 33(11), 995–1003.
  7. Ortega, R., Spong, M. W., Gómez-Estern, F., & Blankenstein, G. (2002). Stabilization of a class of underactuated mechanical systems via interconnection and damping assignment. IEEE Transactions on Automatic Control, 47(8), 1218–1233.
  8. Canudas de Wit, C., Siciliano, B., & Bastin, G. (1996). Theory of robot control. Springer, selected journal articles and chapters on joint PD/PID design.