Chapter 1: Introduction to Adaptive Control

Lesson 2: What is Adaptive Control? Basic Concepts and Goals

This lesson introduces adaptive control as a feedback-control philosophy in which controller parameters are adjusted online using measured signals. Students already familiar with Linear Control will now see how uncertainty, tracking error, online tuning, and stability requirements are organized mathematically before studying MRAC, self-tuning regulators, and adaptive backstepping in later lessons.

1. Definition and Motivation

A fixed-parameter controller has gains selected offline. An adaptive controller contains a feedback controller plus an online adjustment mechanism that changes controller parameters using measured data. The adjustment is not arbitrary; it must be designed so that closed-loop signals remain bounded and the performance error is reduced.

A broad mathematical representation is \( \dot{\mathbf{x} } = f(\mathbf{x},u,\boldsymbol{\theta},t) \), where \( \boldsymbol{\theta} \) contains unknown or slowly varying parameters. An adaptive controller uses an adjustable estimate \( \hat{\boldsymbol{\theta} }(t) \):

\[ \begin{aligned} \dot{\mathbf{x} } &= f(\mathbf{x},u,\boldsymbol{\theta},t),\\ u &= C(\mathbf{x},r,\hat{\boldsymbol{\theta} },t),\\ \dot{\hat{\boldsymbol{\theta} } } &= F(e,\mathbf{x},r,\hat{\boldsymbol{\theta} },t), \end{aligned} \]

Here \( r(t) \) is the command or reference signal, \( e(t) \) is a regulation or tracking error, and \( F(\cdot) \) is the adaptation law. The central goal is not merely to estimate physical parameters; the central goal is to maintain useful closed-loop behavior when the exact plant model is not known.

2. Basic Architecture of an Adaptive Control Loop

Every adaptive controller contains at least three interacting layers: the plant, the adjustable controller, and the adaptation mechanism. The feedback controller acts on the plant immediately, while the adaptation mechanism updates controller parameters based on performance data.

flowchart TD
  R["Reference input r"] --> C["Adjustable controller: \nu = C(x, r, theta_hat)"]
  C --> U["Control input u"]
  U --> P["Uncertain plant"]
  P --> X["Measured output or state"]
  X --> E["Tracking error e"]
  R --> E
  E --> A["Adaptation law: \nupdate theta_hat"]
  X --> A
  A --> C
  P --> D["Unknown parameters \ntheta and disturbances"]
        

Notice the difference from ordinary gain tuning. In ordinary tuning, gains are selected before operation. In adaptive control, the controller contains a dynamic system whose states are the adjustable parameters.

\[ \hat{\boldsymbol{\theta} }(t) = \hat{\boldsymbol{\theta} }(0) + \int_0^t F(e(\tau),\mathbf{x}(\tau),r(\tau), \hat{\boldsymbol{\theta} }(\tau),\tau)\,d\tau. \]

3. What Makes a Controller Adaptive?

A controller is adaptive if its adjustable parameters are updated during operation according to a rule driven by measured closed-loop signals. A typical adjustable control law has the form

\[ u(t)=\hat{\boldsymbol{\theta} }^{T}(t)\boldsymbol{\phi}(t), \]

where \( \boldsymbol{\phi}(t) \) is a regressor vector made from measurable signals such as states, outputs, references, or filtered versions of those signals. The parameter-estimation error is usually written as

\[ \tilde{\boldsymbol{\theta} }(t) = \hat{\boldsymbol{\theta} }(t)-\boldsymbol{\theta}^{*}, \]

where \( \boldsymbol{\theta}^{*} \) denotes the ideal parameter vector that would produce the desired closed-loop behavior if it were known. The value \( \boldsymbol{\theta}^{*} \) may not be a physical plant parameter; it can be an ideal controller parameter.

A common adaptive law has gradient-like structure:

\[ \dot{\hat{\boldsymbol{\theta} } } = -\boldsymbol{\Gamma}\boldsymbol{\phi}(t)e(t), \qquad \boldsymbol{\Gamma}=\boldsymbol{\Gamma}^{T}\succ 0. \]

The matrix \( \boldsymbol{\Gamma} \) is the adaptation gain. Large adaptation gains can improve the speed of adjustment, but they can also amplify measurement noise and create undesirable transients. Detailed tuning and robustness modifications are introduced in later chapters.

4. Goals of Adaptive Control

Adaptive control has several goals. The first goal is closed-loop stability; all internal signals must remain bounded. The second goal is tracking or regulation; the plant output should follow a desired reference or approach a desired equilibrium. The third goal is useful parameter adjustment; the controller should compensate for uncertainty without requiring an exact offline model.

\[ \sup_{t\geq 0} \left( \|\mathbf{x}(t)\|+\|\hat{\boldsymbol{\theta} }(t)\|+|u(t)| \right) < \infty. \]

For tracking problems, the error is often measured by an energy-like performance integral:

\[ J(t) = \frac{1}{2} \int_0^t \left( \mathbf{e}^{T}(\tau)\mathbf{Q}\mathbf{e}(\tau) + \rho u^2(\tau) \right)d\tau, \qquad \mathbf{Q}=\mathbf{Q}^{T}\succ 0,\quad \rho>0. \]

Unlike optimal control, adaptive control does not normally minimize \( J(t) \) exactly. Instead, the cost is a useful way to describe tracking quality and control effort. The stability proof is usually built from Lyapunov-like functions rather than from direct cost minimization.

5. Minimal Scalar Example: Online Adjustment of Two Gains

Consider a first-order plant with uncertain parameters:

\[ \dot{x}=a_p x+b_p u,\qquad b_p>0, \]

and a desired reference model:

\[ \dot{x}_m=a_m x_m+b_m r,\qquad a_m<0. \]

Use the adjustable controller

\[ u=\hat{k}_x x+\hat{k}_r r. \]

If the ideal gains \( k_x^{*} \) and \( k_r^{*} \) were known, they would satisfy the matching conditions

\[ a_p+b_p k_x^{*}=a_m,\qquad b_p k_r^{*}=b_m. \]

Therefore,

\[ k_x^{*}=\frac{a_m-a_p}{b_p}, \qquad k_r^{*}=\frac{b_m}{b_p}. \]

Define the tracking error and parameter errors:

\[ e=x-x_m,\qquad \tilde{k}_x=\hat{k}_x-k_x^{*},\qquad \tilde{k}_r=\hat{k}_r-k_r^{*}. \]

Subtracting the reference model from the plant equation gives the error dynamics

\[ \dot{e} = a_m e+b_p\tilde{k}_x x+b_p\tilde{k}_r r. \]

A basic adaptive law is

\[ \dot{\hat{k} }_x=-\gamma_x x e,\qquad \dot{\hat{k} }_r=-\gamma_r r e, \qquad \gamma_x>0,\quad \gamma_r>0. \]

This example is not yet the full MRAC theory; it is a controlled introductory example showing how adaptation is designed to cancel troublesome cross terms in a Lyapunov derivative.

6. Boundedness Proof for the Scalar Example

Choose the Lyapunov-like function

\[ V(e,\tilde{k}_x,\tilde{k}_r) = \frac{1}{2}e^2 + \frac{b_p}{2\gamma_x}\tilde{k}_x^2 + \frac{b_p}{2\gamma_r}\tilde{k}_r^2. \]

Since \( b_p>0 \) and \( \gamma_x,\gamma_r>0 \), the function is positive definite in \( e,\tilde{k}_x,\tilde{k}_r \). Its time derivative is

\[ \dot{V} = e\dot{e} + \frac{b_p}{\gamma_x}\tilde{k}_x\dot{\hat{k} }_x + \frac{b_p}{\gamma_r}\tilde{k}_r\dot{\hat{k} }_r. \]

Substitute the error dynamics and adaptive laws:

\[ \begin{aligned} \dot{V} &= e(a_m e+b_p\tilde{k}_x x+b_p\tilde{k}_r r) + \frac{b_p}{\gamma_x}\tilde{k}_x(-\gamma_x x e) + \frac{b_p}{\gamma_r}\tilde{k}_r(-\gamma_r r e)\\ &= a_m e^2 + b_p e\tilde{k}_x x + b_p e\tilde{k}_r r - b_p\tilde{k}_x x e - b_p\tilde{k}_r r e\\ &= a_m e^2. \end{aligned} \]

Because \( a_m<0 \),

\[ \dot{V}=a_m e^2 \leq 0. \]

Hence \( V(t)\leq V(0) \), which implies bounded tracking error and bounded adaptive gains. Full asymptotic convergence arguments require additional tools such as uniform continuity and will be developed later in the course.

7. Goal Hierarchy and Design Logic

Adaptive control design should be organized from safety-critical requirements to performance requirements. Parameter convergence is useful but secondary; the plant must remain controlled even if parameters do not converge exactly.

flowchart TD
  A["Start with uncertain plant model"] --> B["Choose measurable tracking error"]
  B --> C["Choose adjustable controller parameters"]
  C --> D["Derive error dynamics"]
  D --> E["Select Lyapunov-like function"]
  E --> F["Choose adaptation law to cancel cross terms"]
  F --> G["Prove boundedness of signals"]
  G --> H["Evaluate tracking, transients, and control effort"]
  H --> I["Tune adaptation gain carefully"]
        

This design logic will reappear throughout the course. Later chapters will add projection, normalization, robust modifications, and persistent excitation analysis.

8. Software Libraries Used in Adaptive Control

Adaptive control implementations often require numerical integration, matrix computation, signal generation, plotting, and sometimes real-time execution. Useful libraries include:

  • Python: NumPy, SciPy, python-control, matplotlib, SymPy for symbolic verification, and slycot where available.
  • C++: Eigen for linear algebra, Boost.Odeint for differential-equation integration, and Qt for GUI-based simulators.
  • Java: Apache Commons Math or EJML for matrix operations and numerical routines.
  • MATLAB/Simulink: Control System Toolbox, Simulink, Stateflow, MATLAB Function blocks, and dedicated adaptive-control blocks where available.
  • Wolfram Mathematica: symbolic algebra, differential equations, Lyapunov-expression manipulation, and visualization.

The following implementations use a dependency-light simulation so that students can focus on the adaptive-control equations rather than installation complexity.

9. Python Implementation

Chapter1_Lesson2.py

"""
Chapter1_Lesson2.py
Basic adaptive control simulation for Lesson 2.
"""

import csv

def reference_signal(t: float) -> float:
    if t < 5.0:
        return 1.0
    if t < 10.0:
        return -0.5
    return 0.75

def simulate(dt: float = 0.001, t_final: float = 15.0):
    a_p = -0.4
    b_p = 1.8
    b_sign = 1.0 if b_p >= 0.0 else -1.0

    a_m = -2.0
    b_m = 2.0

    gamma_x = 4.0
    gamma_r = 4.0

    x = 0.0
    x_m = 0.0
    kx_hat = 0.0
    kr_hat = 0.0

    kx_star = (a_m - a_p) / b_p
    kr_star = b_m / b_p

    data = []
    n_steps = int(t_final / dt)

    for step in range(n_steps + 1):
        t = step * dt
        r = reference_signal(t)
        e = x - x_m
        u = kx_hat * x + kr_hat * r

        x_dot = a_p * x + b_p * u
        x_m_dot = a_m * x_m + b_m * r

        kx_dot = -gamma_x * b_sign * x * e
        kr_dot = -gamma_r * b_sign * r * e

        x += dt * x_dot
        x_m += dt * x_m_dot
        kx_hat += dt * kx_dot
        kr_hat += dt * kr_dot

        if step % 20 == 0:
            data.append({
                "t": t,
                "r": r,
                "x": x,
                "x_m": x_m,
                "e": e,
                "u": u,
                "kx_hat": kx_hat,
                "kr_hat": kr_hat,
                "kx_star": kx_star,
                "kr_star": kr_star,
            })
    return data

def main():
    data = simulate()
    last = data[-1]
    print(f"x={last['x']:.5f}, xm={last['x_m']:.5f}, e={last['e']:.5f}")
    print(f"kx_hat={last['kx_hat']:.5f}, kr_hat={last['kr_hat']:.5f}")

    with open("Chapter1_Lesson2_results.csv", "w", newline="") as f:
        writer = csv.DictWriter(f, fieldnames=list(data[0].keys()))
        writer.writeheader()
        writer.writerows(data)

if __name__ == "__main__":
    main()
      

10. C++ Implementation

Chapter1_Lesson2.cpp

#include <cmath>
#include <fstream>
#include <iomanip>
#include <iostream>

double reference_signal(double t) {
    if (t < 5.0) return 1.0;
    if (t < 10.0) return -0.5;
    return 0.75;
}

int main() {
    const double dt = 0.001;
    const double t_final = 15.0;

    const double a_p = -0.4;
    const double b_p = 1.8;
    const double b_sign = (b_p >= 0.0) ? 1.0 : -1.0;

    const double a_m = -2.0;
    const double b_m = 2.0;

    const double gamma_x = 4.0;
    const double gamma_r = 4.0;

    double x = 0.0;
    double x_m = 0.0;
    double kx_hat = 0.0;
    double kr_hat = 0.0;

    const double kx_star = (a_m - a_p) / b_p;
    const double kr_star = b_m / b_p;

    std::ofstream file("Chapter1_Lesson2_results_cpp.csv");
    file << "t,r,x,x_m,e,u,kx_hat,kr_hat,kx_star,kr_star\n";
    file << std::fixed << std::setprecision(8);

    const int n_steps = static_cast<int>(t_final / dt);
    for (int step = 0; step <= n_steps; ++step) {
        double t = step * dt;
        double r = reference_signal(t);
        double e = x - x_m;

        double u = kx_hat * x + kr_hat * r;

        double x_dot = a_p * x + b_p * u;
        double x_m_dot = a_m * x_m + b_m * r;

        double kx_dot = -gamma_x * b_sign * x * e;
        double kr_dot = -gamma_r * b_sign * r * e;

        x += dt * x_dot;
        x_m += dt * x_m_dot;
        kx_hat += dt * kx_dot;
        kr_hat += dt * kr_dot;

        if (step % 20 == 0) {
            file << t << "," << r << "," << x << "," << x_m << ","
                 << e << "," << u << "," << kx_hat << ","
                 << kr_hat << "," << kx_star << "," << kr_star << "\n";
        }
    }

    std::cout << "Final x=" << x
              << ", xm=" << x_m
              << ", e=" << (x - x_m) << "\n";
    return 0;
}
      

11. Java Implementation

Chapter1_Lesson2.java

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

public class Chapter1_Lesson2 {
    static double referenceSignal(double t) {
        if (t < 5.0) return 1.0;
        if (t < 10.0) return -0.5;
        return 0.75;
    }

    public static void main(String[] args) throws IOException {
        final double dt = 0.001;
        final double tFinal = 15.0;

        final double aP = -0.4;
        final double bP = 1.8;
        final double bSign = (bP >= 0.0) ? 1.0 : -1.0;

        final double aM = -2.0;
        final double bM = 2.0;

        final double gammaX = 4.0;
        final double gammaR = 4.0;

        double x = 0.0;
        double xM = 0.0;
        double kxHat = 0.0;
        double krHat = 0.0;

        final double kxStar = (aM - aP) / bP;
        final double krStar = bM / bP;

        try (PrintWriter out =
             new PrintWriter(new FileWriter("Chapter1_Lesson2_results_java.csv"))) {
            out.println("t,r,x,x_m,e,u,kx_hat,kr_hat,kx_star,kr_star");

            int nSteps = (int) (tFinal / dt);
            for (int step = 0; step <= nSteps; step++) {
                double t = step * dt;
                double r = referenceSignal(t);
                double e = x - xM;

                double u = kxHat * x + krHat * r;

                double xDot = aP * x + bP * u;
                double xMDot = aM * xM + bM * r;

                double kxDot = -gammaX * bSign * x * e;
                double krDot = -gammaR * bSign * r * e;

                x += dt * xDot;
                xM += dt * xMDot;
                kxHat += dt * kxDot;
                krHat += dt * krDot;

                if (step % 20 == 0) {
                    out.printf("%.8f,%.8f,%.8f,%.8f,%.8f,%.8f,%.8f,%.8f,%.8f,%.8f%n",
                            t, r, x, xM, e, u, kxHat, krHat, kxStar, krStar);
                }
            }
        }

        System.out.printf("Final x=%.5f, xm=%.5f, e=%.5f%n", x, xM, x - xM);
    }
}
      

12. MATLAB / Simulink Implementation

Chapter1_Lesson2.m

% Chapter1_Lesson2.m
clear; clc;

dt = 0.001;
t_final = 15.0;
t = 0:dt:t_final;

a_p = -0.4;
b_p = 1.8;
b_sign = sign(b_p);

a_m = -2.0;
b_m = 2.0;

gamma_x = 4.0;
gamma_r = 4.0;

kx_star = (a_m - a_p) / b_p;
kr_star = b_m / b_p;

x = zeros(size(t));
x_m = zeros(size(t));
e = zeros(size(t));
u = zeros(size(t));
kx_hat = zeros(size(t));
kr_hat = zeros(size(t));

for k = 1:length(t)-1
    if t(k) < 5.0
        r = 1.0;
    elseif t(k) < 10.0
        r = -0.5;
    else
        r = 0.75;
    end

    e(k) = x(k) - x_m(k);
    u(k) = kx_hat(k) * x(k) + kr_hat(k) * r;

    x_dot = a_p * x(k) + b_p * u(k);
    x_m_dot = a_m * x_m(k) + b_m * r;

    kx_dot = -gamma_x * b_sign * x(k) * e(k);
    kr_dot = -gamma_r * b_sign * r * e(k);

    x(k+1) = x(k) + dt * x_dot;
    x_m(k+1) = x_m(k) + dt * x_m_dot;
    kx_hat(k+1) = kx_hat(k) + dt * kx_dot;
    kr_hat(k+1) = kr_hat(k) + dt * kr_dot;
end

e(end) = x(end) - x_m(end);

figure;
plot(t, x, 'LineWidth', 1.2); hold on;
plot(t, x_m, '--', 'LineWidth', 1.2);
grid on;
xlabel('time (s)');
ylabel('state');
legend('plant x', 'reference x_m');
title('Chapter 1 Lesson 2: Basic Adaptive Tracking');

results = table(t(:), x(:), x_m(:), e(:), u(:), kx_hat(:), kr_hat(:), ...
    'VariableNames', {'t','x','x_m','e','u','kx_hat','kr_hat'});
writetable(results, 'Chapter1_Lesson2_results_matlab.csv');

% Simulink construction idea:
% 1) Use Integrator blocks for x, x_m, kx_hat, and kr_hat.
% 2) Build u = kx_hat*x + kr_hat*r with Product and Sum blocks.
% 3) Build adaptation laws with Product and Gain blocks.
      

13. Wolfram Mathematica Implementation

Chapter1_Lesson2.nb

ClearAll[referenceSignal, dt, tFinal, aP, bP, bSign, aM, bM, gammaX, gammaR];

referenceSignal[t_] := Piecewise[{ {1.0, t < 5.0}, {-0.5, t < 10.0} }, 0.75];

dt = 0.001; tFinal = 15.0;
aP = -0.4; bP = 1.8; bSign = Sign[bP];
aM = -2.0; bM = 2.0;
gammaX = 4.0; gammaR = 4.0;

kxStar = (aM - aP)/bP;
krStar = bM/bP;

x = 0.0; xm = 0.0; kxHat = 0.0; krHat = 0.0;

data = Reap[
  Do[
    t = step*dt;
    r = referenceSignal[t];
    e = x - xm;
    u = kxHat*x + krHat*r;

    xDot = aP*x + bP*u;
    xmDot = aM*xm + bM*r;

    kxDot = -gammaX*bSign*x*e;
    krDot = -gammaR*bSign*r*e;

    x = x + dt*xDot;
    xm = xm + dt*xmDot;
    kxHat = kxHat + dt*kxDot;
    krHat = krHat + dt*krDot;

    If[Mod[step, 20] == 0, Sow[{t, r, x, xm, e, u, kxHat, krHat}]],
    {step, 0, Floor[tFinal/dt]}
  ]
][[2, 1]];

ListLinePlot[
  {data[[All, {1, 3}]], data[[All, {1, 4}]]},
  PlotLegends -> {"plant x", "reference xm"},
  AxesLabel -> {"time (s)", "state"},
  PlotLabel -> "Chapter 1 Lesson 2: Basic Adaptive Tracking"
]
      

14. Problems and Solutions

Problem 1: Explain the difference between a fixed-parameter controller and an adaptive controller using mathematical notation.

Solution: A fixed-parameter controller can be written as \( u=C(\mathbf{x},r,\boldsymbol{\theta}_c) \), where \( \boldsymbol{\theta}_c \) is constant after design. An adaptive controller uses \( u=C(\mathbf{x},r,\hat{\boldsymbol{\theta} }(t)) \) together with a dynamic update law \( \dot{\hat{\boldsymbol{\theta} } }=F(e,\mathbf{x},r,\hat{\boldsymbol{\theta} },t) \). Thus, the controller itself contains a parameter-update dynamic.

Problem 2: For the scalar plant \( \dot{x}=a_p x+b_p u \) and controller \( u=\hat{k}_x x+\hat{k}_r r \), derive the ideal matching gains for the reference model \( \dot{x}_m=a_m x_m+b_m r \).

Solution: If perfect model matching is possible, then substituting the ideal controller into the plant gives

\[ \dot{x} = (a_p+b_p k_x^{*})x + b_p k_r^{*}r. \]

Matching coefficients with the reference model gives

\[ a_p+b_p k_x^{*}=a_m,\qquad b_p k_r^{*}=b_m. \]

Therefore,

\[ k_x^{*}=\frac{a_m-a_p}{b_p}, \qquad k_r^{*}=\frac{b_m}{b_p}. \]

Problem 3: For the same scalar example, derive the tracking-error dynamics using \( e=x-x_m \).

Solution: Since \( \dot{e}=\dot{x}-\dot{x}_m \),

\[ \dot{e} = a_p x+b_p(\hat{k}_x x+\hat{k}_r r) - (a_m x_m+b_m r). \]

Add and subtract the ideal matched terms and use \( e=x-x_m \):

\[ \dot{e} = a_m e+b_p\tilde{k}_x x+b_p\tilde{k}_r r. \]

Problem 4: Show that the adaptive laws \( \dot{\hat{k} }_x=-\gamma_x x e \) and \( \dot{\hat{k} }_r=-\gamma_r r e \) make the Lyapunov derivative nonpositive for \( b_p>0 \).

Solution: Use

\[ V= \frac{1}{2}e^2+ \frac{b_p}{2\gamma_x}\tilde{k}_x^2+ \frac{b_p}{2\gamma_r}\tilde{k}_r^2. \]

Differentiation and substitution give

\[ \dot{V} = a_m e^2. \]

Since \( a_m<0 \), we have \( \dot{V}\leq 0 \). Thus the Lyapunov function does not increase, and the variables included in \( V \) remain bounded.

Problem 5: Does boundedness of \( \hat{k}_x(t) \) and \( \hat{k}_r(t) \) automatically mean that the estimates converge to the ideal gains?

Solution: No. Boundedness means the estimates do not diverge, but exact parameter convergence requires sufficient information in the measured signals. If the reference input and regressor do not sufficiently excite the plant, many parameter values may produce similar tracking behavior. This issue is studied later under persistent excitation.

15. Summary

Adaptive control augments feedback control with online parameter adjustment. The objective is not simply to identify plant parameters, but to preserve stability and improve performance under uncertainty. The minimal scalar example showed the key idea: choose an adaptation law so that troublesome cross terms in the Lyapunov derivative cancel. This prepares the ground for the classification of adaptive controllers in the next lesson.

16. References

  1. Kalman, R.E. (1958). Design of a self-optimizing control system. Transactions of the ASME, 80, 468–478.
  2. Parks, P.C. (1966). Liapunov redesign of model reference adaptive control systems. IEEE Transactions on Automatic Control, 11(3), 362–367.
  3. Åström, K.J., & Wittenmark, B. (1973). On self-tuning regulators. Automatica, 9(2), 185–199.
  4. Monopoli, R.V. (1974). Model reference adaptive control with an augmented error signal. IEEE Transactions on Automatic Control, 19(5), 474–484.
  5. Narendra, K.S., & Valavani, L.S. (1980). A comparison of Lyapunov and hyperstability approaches to adaptive control of continuous systems. IEEE Transactions on Automatic Control, 25(2), 243–247.
  6. Goodwin, G.C., Ramadge, P.J., & Caines, P.E. (1980). Discrete-time multivariable adaptive control. IEEE Transactions on Automatic Control, 25(3), 449–456.
  7. Rohrs, C.E., Valavani, L., Athans, M., & Stein, G. (1985). Robustness of continuous-time adaptive control algorithms in the presence of unmodeled dynamics. IEEE Transactions on Automatic Control, 30(9), 881–889.
  8. Morse, A.S. (1992). High-order parameter tuners for the adaptive control of linear and nonlinear systems. Systems & Control Letters, 18(1), 1–7.
  9. Ioannou, P.A., & Kokotovic, P.V. (1984). Instability analysis and improvement of robustness of adaptive control. Automatica, 20(5), 583–594.
  10. Annaswamy, A.M., & Fradkov, A.L. (2021). A historical perspective of adaptive control and learning. Annual Reviews in Control, 52, 18–41.
Support CaaT Academy

Help keep these engineering tutorials free and growing

If these lessons, examples, and project pages help you, a small donation supports the continued creation and improvement of free control, robotics, software, and engineering education resources.

Created and maintained by Abolfazl Mohammadijoo.