Lie-Klammer für die Exakte Eingangs-Zustandslinearisierung

Kybernetik
Regelungstechnik
Flachheit
Autor:in

Johannes Kaisinger

Veröffentlichungsdatum

2. März 2022

Bei der Eingangs-Zustandslinearisierung ist der Ausgang \(y\) des nichtlinearen Systems nicht relevant. Es gibt eine gut ausgebaute Theorie, welche die Überprüfung der Eingangs-Zustands-Linearisierbarkeit erlaubt.

Für die Überprüfung der Existenz eines Ausganges mit relativem Grad \(r=n\) erweist sich die Lie-Klammer als hilfreich. Das gilt sowohl für Ein- als auch Mehrgrößensysteme (SISO und MIMO Systeme).

Die Theorie der differential-geometrischen Regelungstechnik ist sehr gut ausgebaut, jedoch alles andere als trivial. Für das Erlernen dieser Techniken sollte viel Zeit eingeplant werden. An den Universitäten werden dafür meist mehrere Vorlesungen benötigt, um diese Theorie vollständig einzuführen.

Es soll hier nur gezeigt werden, dass Python / Sympy auf für nichtlineare Methoden gut geeignet ist.

Lie-Klammer

Die Lie-Klammer ist folgendermaßen definiert

\[ [f, g](x) = L_f g(x) = \frac{\partial g}{\partial x} f(x) - \frac{\partial f}{\partial x} g(x) \]

wobei hier sowohl \(f(x)\) als auch \(g(x)\) Vektorfelder sind.

Auch die Lie-Klammer (Lie-Ableitung der Vektorfelder) kann wie die Lie-Ableitung der skalaren Funktionen rekursive angewendet werden. Die k-fache Lie-Klammer lässt sich in der Form

\[ ad_f^kg(x) = \begin{bmatrix} f & ad_f^{k-1}g \end{bmatrix}(x) \qquad ad_f^0g(x) = g(x) \]

mit dem Operator \(ad\) definieren.

Hinweis

Existenz eines Ausganges mit relativem Grad r = n)

Für SISO Systeme ist es notwendig aber nicht hinreichend, dass die Matrix

\[ M = \begin{bmatrix}g & ad_f g & \cdots & ad_f^{n-1} g\end{bmatrix} \]

den Rang \(n\) besitzt.

Beispiel

Dieses Beispiel ist aus dem Vorlesungskript von Andreas Kugi, TU Wien entnommen.

Gegeben sei das AI-System

\[ \dot{x} = \underset{f(x)}{\underbrace{ \begin{bmatrix} x_3 \\ x_4 \\ - \frac{c}{I_1} x_1 + \frac{c}{I_1} x_2 - \frac{d_1}{I_1} x_3 \\ \frac{c}{I_2} x_1 - \frac{c}{I_2} x_2 - \frac{mgl}{I_2} cos(x_2) - \frac{d_2}{I_2} x_4 \end{bmatrix}}} + \underset{g(x)}{\underbrace{ \begin{bmatrix} 0 \\ 0 \\ \frac{1}{I_1} \\ 0 \end{bmatrix}}} u. \]

Das Durchführen der Rechnung führt auf das Ergebnis

\[ rang(\begin{bmatrix}ad_f^0g & ad_f^1g & ad_f^2g & ad_f^3g\end{bmatrix}) = rang \left(\begin{bmatrix} 0 & \frac{-1}{I_1} & \frac{-d_1}{I_1^2} & \frac{I_1c-d_1^2}{I_1^3} \\ 0 & 0 & 0 & -\frac{c}{I_2I_1} \\ \frac{1}{I_1} & \frac{d_1}{I_1^2} & \frac{d_1^2-cI_1}{I_1^3} & \frac{d_1^3-2cd_1I_1}{I_4^4} \\ 0 & 0 & \frac{c}{I_2I_1} & \frac{c}{I_2I_1}\left(\frac{d_1}{I_1} + \frac{d_2}{I_2} \right) \end{bmatrix}\right) = 4. \]

Wir wollen diese Berechnung nun in Python / Sympy durchführen.

from sympy import init_printing
init_printing()

from sympy import *
def jac(f,x):
    return f.jacobian(x)
def lie_deriv(f, h, x, n=1):
    """ Lie-derivative of a scalar function h with respect to a vector-field f
    """
    if n==0:
        Lfh = h
    else:
        Lfh = h.jacobian(x)@f
        for i in range(1,n):
            Lfh = Lfh.jacobian(x)@f
    return Lfh
def lie_braket(f, g, x, n=1):
    """ Lie-bracket, Lie-derivative of a vector-field g with respect to another vector-field f
    """
    if n==0:
        adfg = g
    else:
        adfg = g.jacobian(x)@f - f.jacobian(x)@g
        for i in range(1,n):
            adfg = adfg.jacobian(x)@f - f.jacobian(x)@adfg
    return adfg
x1, x2, x3, x4 = symbols('x1 x2 x3 x4', real=True)
x_vec =  Matrix([[x1],[x2],[x3],[x4]])
c, g, l, m = symbols('c g l m', positive=True)
I1, d1 = symbols('I1 d1', positive=True)
I2, d2 = symbols('I2 d2', positive=True)
f = Matrix([
    [x3],
    [x4],
    [-c/I1*x1+c/I1*x2-d1/I1*x3],
    [c/I2*x1-c/I2*x2-m*g*l/I2*cos(x2)-d2/I2*x4]
           ])

f

\(\displaystyle \left[\begin{matrix}x_{3}\\x_{4}\\- \frac{c x_{1}}{I_{1}} + \frac{c x_{2}}{I_{1}} - \frac{d_{1} x_{3}}{I_{1}}\\\frac{c x_{1}}{I_{2}} - \frac{c x_{2}}{I_{2}} - \frac{d_{2} x_{4}}{I_{2}} - \frac{g l m \cos{\left(x_{2} \right)}}{I_{2}}\end{matrix}\right]\)

g = Matrix([
    [0],
    [0],
    [1/I1],
    [0]
])
g

\(\displaystyle \left[\begin{matrix}0\\0\\\frac{1}{I_{1}}\\0\end{matrix}\right]\)

adf0g = lie_braket(f, g, x_vec,n=0)
adf1g = lie_braket(f, g, x_vec,n=1)
adf2g = lie_braket(f, g, x_vec,n=2)
adf3g = lie_braket(f, g, x_vec,n=3)
M = adf0g
M = M.col_insert(1,adf1g)
M = M.col_insert(2,adf2g)
M = M.col_insert(3,adf3g)
simplify(M)

\(\displaystyle \left[\begin{matrix}0 & - \frac{1}{I_{1}} & - \frac{d_{1}}{I_{1}^{2}} & \frac{I_{1} c - d_{1}^{2}}{I_{1}^{3}}\\0 & 0 & 0 & - \frac{c}{I_{1} I_{2}}\\\frac{1}{I_{1}} & \frac{d_{1}}{I_{1}^{2}} & \frac{- I_{1} c + d_{1}^{2}}{I_{1}^{3}} & \frac{d_{1} \left(- 2 I_{1} c + d_{1}^{2}\right)}{I_{1}^{4}}\\0 & 0 & \frac{c}{I_{1} I_{2}} & \frac{c \left(I_{1} d_{2} + I_{2} d_{1}\right)}{I_{1}^{2} I_{2}^{2}}\end{matrix}\right]\)

M.rank()

\(\displaystyle 4\)

Die Matrix

\[ M = \begin{bmatrix}ad_f^0g & ad_f^1g & ad_f^2g & ad_f^3g\end{bmatrix} \]

hat also den vollen Rang \(n=4\) und der relative Grad ist also \(r=4\).

Fazit

Python / Sympy bietet viele Möglichkeiten für die nichtlineare Regelungtechnik. Dieser Blogeintrag bezieht sich auf differentialgeometrischen Methoden, genauer auf die Exakte Eingangs-Zustandslinearisierung im Eingrößenfall.

Sind die nichtlinearen Regler einmal hergeleitet, so können diese mithilfe der Python-Control Submodule wie control.flatsys oder control.NonlinearIOSystem implementiert werden.

Referenzen

  • Nichtlineare Systeme und Regelungen, 3. Auflage (Jürgen Adamy, 2018)
  • The Geometry of Physics, Third Edition (Theodore Frankel, 2012)
  • Regelsysteme 2 (Andreas Kugi, Vorlesung SS 2021)