import numpy as np
import matplotlib.pyplot as plt
'ggplot')
plt.style.use(
import control as ct
Wir wollen hier nun ein einfaches Beispiel der Klasse Model-Reference Adaptive Control (MRAC) besprechen. Die MRAC Methoden haben eine große praktische Relevanz, insbesondere in der Luft- und Raumfahrt (Helicopter, Multicopter, Drohnen, Militärjets, …). MRAC ist ein sogenanntes Tracking Problem.
Model-Reference Adpative Control (MRAC)
Erste Varianten von Model-Reference Adpative Control (MRAC) Methoden wurden in den 1950er und 1960er Jahren erarbeitet. Auch werden MRAC Konzepte mit Gauss-Prozessen oder neuronalen Netzen kombiniert. Aus einer Regelungstechnik-Perspektive sind diese Ansätze deswegen attraktiv, weil viele Einsichten der Kontrolltheorie hier weiter verwendet werden können.
Die Idee von MRAC, besteht darin, das gewünschte Verhalten mithilfe eines Referenz-Modells vorzugeben. Ein Regler besitzt nun adaptierbare Parameter, welche so lange verändert werden, bis der reale Ausgang dem Modellausgang entspricht.
MIT Rule
Wir betrachten einen geschlossenen Regelkreis, wo der Regler anpassbare Parameter \(\theta\) besitzt. Das gewünschte Verhalten des geschlossenen Regelkreises wird mithilfe eines Referenz-Modells spezifiziert, dessen Ausgang mit \(y_r\) bezeichnet wird. Nun können wir einen Fehler \(e = y_r - y_p\) einführen, welcher die Differenz zwischen dem Modellausgang \(y_r\) und dem Prozessausgang \(y_p\) misst.
Eine Möglichkeit besteht darin, die Parameter \(\theta\) so anzupassen, dass das Gütefunktional
\[ J(\theta) = \frac{1}{2}e^2 \]
minimiert wird. Um \(J\) kleiner zu machen ist es sinnvoll, die Parameter in Richtung des negative Gradienten von \(J\) anzupassen, sodass gilt
\[ \frac{d\theta}{dt} = - \gamma \frac{\partial J}{\partial \theta} = - \gamma e \frac{\partial e}{\partial \theta} \]
Dieses Adaptionsgesetzt wird als MIT Rule bezeichnet, und geht auf ein Labor am Massachusetts Institute of Technology (MIT) zurück. Die partielle Ableitung \(\dfrac{\partial e}{\partial \theta}\) wird als Sensitivitätsableitung (sensitivity derivative) bezeichnet, und beschreibt den Einfluss der Parameter auf den Fehler.
Direct MRAC: Adaption der Verstärkung
Im Folgendem betrachten wir ein Problem, wo nur eine Verstärkung adaptiert werden soll. Es ist wohl das einfachste MRAC-Problem. Es sei angenommen, dass ein linearer Prozess \(bG(s)\) gegeben ist, wobei \(G(s)\) eine bekannte Übertragungsfunktion und \(b\) ein unbekannter Parameter ist.
Weiters sei das Referenz-Modell \(G_r(s) = b_rG(s)\) gegeben. Mithilfe des Referenz-Eingangs \(u_r\) und dem Referenz-Modell \(G_r(s)\) wird der Modellausgang \(y_r\) erzeugt. Das Problem ist nun, einen Regler zu finden, der dem Modellausgang \(y_r\) folgt. Mit dem Steuerungsgesetz
\[ u_p = \theta u_r \]
ergibt sich für den Ausgang \(y_p(t) = \theta b G(p) u_r(t)\), wobei \(p = \dfrac{d}{dt}\) ein differential Operator ist. Diese Übertragungsfunktion ist gleich zu \(G_r(s) = b_rG(s)\), wenn für den adaptiven Parameter
\[ \theta = \frac{b_r}{b} \]
gilt.
Für diesen Fall stimmt der Ausgang \(y_p\) der realen Strecke mit dem Ausgang \(y_r\) des Modells überein. Wir wollen das MIT-Gesetzt anwenden, um eine Anpassungsmethode herzuleiten.
Der Fehler ist mit
\[ e = y_r - y_p = + b_rG(p)u_r - b G(p) \theta u_p \]
gegeben, wobei \(u_r\) als das Referenz-Eingangssignal, \(y_r\) als der Modellausgang, \(y_p\) als der Prozessausgang und \(\theta\) als der Anpassungsparameter bezeichnet wird.
Die Sensitivitätsableitung ist mit
\[ \frac{\partial e}{\partial \theta} = - bG(p)u_p = - \frac{b}{b_r} y_r \]
gegeben. Hier wurden die Beziehungen \(y_r = b G(p) \theta u_p\) und \(\theta= \dfrac{b_r}{b}\) genutzt, welche für \(e = 0\) gelten.
Das Adaptionsgesetz ergibt sich nun zu
\[ \frac{d \theta}{d t} = \gamma^{\prime} \frac{b}{b_r} y_r e = \gamma y_r e \cdot \text{sign}(b) \]
mit \(\gamma = \gamma^{\prime} \dfrac{b}{b_r}\) . Das Adaptionsgesetz ist somit unabhängig von dem unbekannten Parameter \(b\), das Vorzeichen muss jedoch bekannt sein.
Die zeitliche und bildliche Darstellungen wollen wir hier nicht vermischen. Deshalb haben wir hier neben der Laplace-Variable \(s\) auch einen Differential-Operator \(p\) eingeführt.
Laplace-Variable \(s\)
Gegeben sei die Übertragungsfunktion
\[ G(s) = \dfrac{1}{s+1} = \dfrac{Y(s)}{U(s)} \]
welche auf die Gleichung
\[ sY(s)+Y(s) = U(s) \]
überführt werden kann.
Differential-Operator \(p\)
Um die Übertragungsfunktion für zeitliche Signale nutzen zu können, verwenden wir den Differential-Operator \(p\). Sowohl \(p\) als auch \(G(p)\) können auf zeitliche Signale angewendet werden, so gilt
\[ y(t) = G(p)(u(t)). \]
Aus
\[ G(p) = \dfrac{1}{p+1} = \dfrac{y(t)}{u(t)} \]
ergibt sich die Gleichung
\[ py(t)+y(t) = \dot{y}(t)+y(t) = u(t). \]
Je nach Kontext bedeutet ein klein geschriebene Variable \(y\) entweder \(y=y(t)\) oder \(y=Y(s)\). Das reduziert die Notation und wird auch in der Literatur verwendet.
Beispiel
Mithilfe von python-control können wir die Regelung implementieren und testen.
Das obige Beispiel soll hier nun implementiert werden. Das Problem sei gegeben durch:
- \(G(s) = \frac{1}{s +1}\) (bekannt)
- \(b = 1\) (unbekannt)
- \(b_r = 2\) (bekannt, da vorgegeben)
- \(\lambda = 0.5, 1. ,2.\) (Adaptions-Verstärkung)
- \(u_r = \sin(0.4 \pi t)\) (Referenz-Signal)
Das Modell $G_r(s) = b_rG(s) = = $ könnten wir in das Zustandsmodell
\[ \dot{y}_r = - y_r + b_r u_r \]
überführen. Wir werden aber weiter die Übertragungsfunktion nutzen.
Die Strecke ist ein lineares System für welches wir die Klasse control.LinearIOSystem
nutzen können.
# linear system
= 1
b = ct.tf('s')
s = b/(1 + s)
G_plant_tf
# io model
= ct.LinearIOSystem(
io_plant
G_plant_tf,=('up'),
inputs=('yp'),
outputs=('xp'),
states='plant'
name )
Das Referenzmodell ist ein lineares System für welches wir die Klasse control.LinearIOSystem
nutzen können.
# linear system
= 2
br = br/(1 + s)
G_model_tf
# io model
= ct.LinearIOSystem(
io_ref_model
G_model_tf,=('ur'),
inputs=('yr'),
outputs=('xr'),
states='ref_model'
name )
Weil viele Adaptionsgesetze nichtlineare Funktionen sind, wollen wir die Klasse control.NonlinearIOSystem
benutzen.
Diese Klasse erlaubt eine Implementation eines nichtlineares Systems der Form
\[ \begin{split} \dot{x} &= f(t, x, u; p) \\ y &= g(t, x, u; p) \\ \end{split}. \]
Dafür werden zwei Funktionen für \(f(t,x,u;p)\) und \(g(t,x,u;p)\) benötigt, welche der Klasse übergeben werden.
def adaptive_controller_state(t, x, u, params):
"""Internal state of adpative controller, f(t,x,u;p)"""
# parameters
= params["gam"] # adaptation gain, aka. learning rate
gam = params["signb"]
signb
# controller inputs
= u[0]
ur = u[1]
yp = u[2]
yr
# controller states
# theta = x[0] # is not needed here
# algebraic relationships
= yr - yp
e
# dynamics xd = f(x,u)
= gam*yr*e*signb
d_theta
return [d_theta]
def adaptive_controller_output(t, x, u, params):
"""Algebraic output from adaptive controller, g(t,x,u;p)"""
# controller inputs
= u[0]
ur = u[1]
yp = u[2]
yr
# controller state
= x[0]
theta
# control law
= theta*ur
up
return [up, theta]
={"gam":1,"signb":np.sign(b)}
params
= ct.NonlinearIOSystem(
io_controller
adaptive_controller_state,
adaptive_controller_output,=3,
inputs=('up', 'theta'),
outputs=1,
states=params,
params='control',
name=0
dt )
Die drei Blöcke können mit control.InterconnectedSystem
zu einem System verbunden werden.
= ct.InterconnectedSystem(
io_closed
(io_plant, io_ref_model, io_controller),=(
connections'plant.up', 'control.up'),
('control.u[1]', 'plant.yp'),
('control.u[2]', 'ref_model.yr')
(
),=('control.u[0]', 'ref_model.ur'),
inplist=('plant.yp', 'ref_model.yr', 'control.up', 'control.theta'),
outlist=0
dt )
# set initial conditions
= np.zeros((3, 1))
X0 0] = 0 # state of system
X0[1] = 0 # state of ref_model
X0[2] = 0 # state of controller X0[
# set simulation duration and time steps
= 20
Tend = 0.1
dt
# define simulation time span
= np.arange(0, Tend, dt)
t_vec # define control input
= np.zeros((2, len(t_vec)))
uc_vec = np.sin(0.3 * np.pi * t_vec)
sin 0, :] = sin
uc_vec[1, :] = uc_vec[0, :] uc_vec[
# simulate the system, with different gammas
= ct.input_output_response(io_closed, t_vec, uc_vec, X0, params={"gam":0.5})
tout1, yout1 = ct.input_output_response(io_closed, t_vec, uc_vec, X0, params={"gam":1})
tout2, yout2 = ct.input_output_response(io_closed, t_vec, uc_vec, X0, params={"gam":2}) tout3, yout3
=(16,8))
plt.figure(figsize2,1,1)
plt.subplot(0,:], label=r'$y_{\gamma = 0.5}$')
plt.plot(tout2, yout1[0,:], label=r'$y_{\gamma = 1.0}$')
plt.plot(tout2, yout2[0,:], label=r'$y_{\gamma = 2.0}$')
plt.plot(tout3, yout3[1,:] ,label=r'$y_{soll}$', linestyle="--")
plt.plot(tout1, yout1[=14)
plt.legend(fontsize'Systemantworten')
plt.title(2,1,2)
plt.subplot(2,:], label=r'$\gamma = 0.5$')
plt.plot(tout1, yout1[2,:], label=r'$\gamma = 1.0$')
plt.plot(tout2, yout2[2,:], label=r'$\gamma = 2.0$')
plt.plot(tout3, yout3[=4, fontsize=14)
plt.legend(locr'Regler $u_p$')
plt.title( plt.show()
=(16,8))
plt.figure(figsize3,:], label=r'$\gamma = 0.5$')
plt.plot(tout1, yout1[3,:], label=r'$\gamma = 1.0$')
plt.plot(tout2, yout2[3,:], label=r'$\gamma = 2.0$')
plt.plot(tout3, yout3[=4, fontsize=14)
plt.legend(locr'Adaptionsparameter $\theta$')
plt.title( plt.show()
Das Diagramm zeigt, dass der Parameter für \(\gamma = 1\) zum wahren Wert konvergiert, und der Ausgang \(y_p\) dem Modellausgang \(y_r\) folgt, was auch unser Ziel war. Die Konvergenzrate hängt von der Anpassungsverstärkung \(\gamma\) ab. Für kleiner Werte konvergiert der Parameter langsamer. Anpassungsverstärkungen basierend auf den Gradientenabstieg können wie Lernraten nie beliebig groß gewählt werden, da sonst womöglich Instabilitäten auftreten.
In der adaptiven Regelung ist es aber nicht immer notwendig, dass die Parameter zu einem wahren Wert konvergieren. Das ist eine der großen Einsichten der adaptiven Regelung. Wenn der Ausgang \(y_p\) schon perfekt dem Referenz-Ausgangssignal folgt, dann gilt \(e=0\) und der Parameter \(\theta\) würde nicht weiter angepasst, selbst wenn noch ein Parameterfehler \(\tilde{\theta}=\theta^{*}-\theta \neq 0\) vorhanden wäre.
Fazit
Autonome Systeme wie mobile Roboter, Drohnen oder selbstfahrende Autos treffen unweigerlich auf Umgebungen, welche entweder unbekannt oder veränderlich sind. Das verlangt von autonomen Systemen eine Anpassungsfähigkeit auf veränderte Umstände. Die adaptive Regelung und das bestärkende Lernen sind zwei Kandidaten, um dieses Ziel zu erreichen.
Aber auch andere Systeme müssen zunehmend adaptiv gestaltet werden. Denken wir nur an die Stromerzeugung durch erneuerbaren Energien und die zunehmende Elektrifizierung des Verkehrssektors wie auch der Industrie. Statische, das heißt nicht adaptive oder lernende Regelungskonzepte sind dort zunehmend, als hinderlich anzusehen. Adaptive Verfahren müssen dabei Garantien hinsichtlich Stabilität, aber auch Robustheit liefern, um eine Freigabe für kritische Systeme zu erhalten.
Referenzen
- Adaptive Control, Second Editon, 2008 (Karl J. Aström, Björn Wittenmark)
- Model-Reference Adaptive Control: A primer, 2018 (Nhan T. Nguyen)
- Robust Adaptive control, 2012 (Petros A. Ioannou, Jing Sun)
- Deep Model Reference Adaptive Control 2019 (Girish Joshi, Girish Chowdhary)