Nachfolgend ist ein Python-Programm gelistet, das ein Mehrgrößensystem in Form einer Übertragungsmatrix darstellt und eine statische Entkopplung berechnet. Darüber hinaus finden Berechnungen in der Zustandsraumdarstellung statt, z.B. Transformation auf RNF.
web701
Mehrgrößensystem G(s)
Listing 7.1: Es erfolgt die Erzeugung eines Mehrgrößensystems mit der Python Control Library und Berechnung der statischen Entkopplungsmatrix. Für die Berechnung von Mehrgrößensystem ist das Paket slycot erforderlich.
# -*- coding: utf-8 -*- """ Erzeugung eines Mehrgrößensystems mit der Python Control Lib und Berechnung der statischen Entkopplung. slycot erforderlich statische Entkopplung funktioniert nicht im Fall integralwirkende Strecke! Created on 22.4. 2019, mod. 20.8.24 @author: philippsen """ import numpy as np import control as ct import matplotlib.pyplot as plt #Gii(s) = 2/2s^2 + 3s +1 Gij = 0.5/2s+1 n11= [2.0]; d11= [2., 3., 1.] n22= [2.0]; d22= [2., 3., 1.] n12= [0.5]; d12= [2., 1.] n21= [0.5]; d21= [2., 1.] g11 = ct.tf(n11,d11); g110 = ct.dcgain(g11) g12 = ct.tf(n12,d12); g120 = ct.dcgain(g12) g22 = ct.tf(n22,d22); g220 = ct.dcgain(g22) g21 = ct.tf(n21,d21); g210 = ct.dcgain(g21) num = [[n11, n12], [n21, n22]] den = [[d11, d12], [d21, d22]] strecke = ct.tf(num, den) k= g110*g220/(g110*g220 - g210*g120) ne = [[[k], [-k*g120/g110]], [[-k*g210/g220], [k]]] de = [[[1.], [1.]], [[1.], [1.]]] ent = ct.tf(ne, de) ct.step_response(strecke).plot(label='ohne Entk.') #plt.figure() ct.step_response(ent*strecke).plot( title='Sprungantwort Mimo stat. Entkopplung',label='mit Entk.')
web702
Standardregelstrecke im Zustandsraum
Listing 7.2: Die Standardregelstrecke wird im Zustandsraum mit der Regelungsnormalform dargestellt und simuliert, gemäß Beispiel 7.7.1.
# -*- coding: utf-8 -*- """ Standardregelstrecke im Zustandsraum in RNF Created on 12.4. 2019, mod. 20.8.24 @author: philippsen """ import numpy as np import control as ct import matplotlib.pyplot as plt a0 = 1./30. a1 = 10./30. a2 = 31./30. b0 = 1./30. A = np.array([[0, 1.,0 ],[ 0, 0, 1. ],[ -a0, -a1, -a2]]) b = np.array([[0.],[ 0. ],[ 1.]]) c = np.array([b0, 0,0 ]) stand = ct.ss(A, b, c, 0) #T = np.linspace(0, 40,num=200) #t, y, x = ct.forced_response(stand,T,U=1,X0=0,return_x=True) t, y, x = ct.step_response(stand,return_x=True) # mit Zuständen plt.plot(t,y) plt.title('Standardregelstrecke im Zustandsraum, RNF') plt.xlabel('t [s]'); plt.ylabel('h(t)') plt.grid()
web703
DC-Motor im Zustandsraum
Listing 7.3: Der DC-Motor 2237 wird im Zustandsraum dargestellt, wobei die Simulation der Drehzahl erfolgt.
# -*- coding: utf-8 -*- """ DC-Motor im Zustandsraum Faulhaber Motor 2237 Created on 16.10. 2018, mod. 20.8.24 @author: philippsen """ import numpy as np; from math import pi import control as ct import matplotlib.pyplot as plt cPsi= 0.0318 # Datenblatt Faulhaber 2237 R = 15.7 # Widerstand Anker L = 590e-6 # Induktivität Anker zpiJ = 47.119e-6 # Schwungmasse Berechnung 2pi7,5e-6 Am = np.array([[-R/L, -2*pi*cPsi/L], [cPsi/zpiJ, 0]]) bm = np.array([[ 1/L],[0]]) cm = np.array([ 0, 1]) C = np.array([[1, 0 ], [0, 1 ]]) # Falls alle Zustände ausgegeben werden sollen D = np.array([[ 0. ],[0]]) DCmot = ct.ss(Am, bm, cm, 0) t, y, x = ct.step_response(DCmot, return_x=True) plt.gcf().clear() # löscht den alten Plot plt.plot(t,y) #plt.plot(t,x[1,:],t,x[0,:]) # mit Stromverlauf plt.title('DC-Motor im Zustandsraum') plt.xlabel('t [s]'); plt.ylabel('n(t)') plt.grid()
web704
Transformation auf Regelungsnormalform
Listing 7.4: Eine Transformation auf RNF wird mit Hilfe des Algorithmus aus Kapitel 7.7.3 durchgeführt und verglichen mit dem Ergebnis der Control Toolbox.
# -*- coding: utf-8 -*- """ Standardregelstrecke im Zustandsraum und Transformation auf RNF Steuerbarkeitsmatrix S, Vergleich mit Control Lib Created on 25.4. 2019, mod. 20.8.24 @author: philippsen """ import numpy as np import control as ct T1 = 2; T2 = 3; T3 = 5 A = np.array([[-1/T1, 0.,0 ],[ 1/T2, -1/T2, 0 ],[ 0, 1/T3, -1/T3]]) b = np.array([[1/T1],[ 0. ],[ 0]]) c = np.array([0, 0,1 ]) stand = ct.ss(A, b, c, 0) # Berechnung Transformationsmatrix auf RNF n = np.size(b) AA = A S = np.zeros((n,n)); T = np.zeros((n,n)) S[:,0] = b.T S[:,1] = np.dot(A,b).T # Aufbau Steuerbarkeitsmatrix for i in range(2,n): AA = np.dot(AA,A) S[:,i] = np.dot(AA,b).T S1 = np.linalg.inv(S) T[0,:] = S1[n-1,:] #letzte Zeile Übernehmen for i in range(1,n): T[i,:] = np.dot(T[i-1,:],A).T print('T = ') print(T,'\n') Arnf = np.mat(T)*np.mat(A)*np.linalg.inv(T) print('Arnf = ') print(Arnf,'\n') zu = ct.ss(A,b,c,0.0) Arnf2, T2 = ct.canonical_form(zu) print('System mit Control Lib auf RNF transformiert:') print(Arnf2)
web705
Pendeldämpfung mit Zustandsregler
Listing 7.5:
# -*- coding: utf-8 -*- """ Kran im Zustandsraum Reglerentwurf mit Ackermann Created on 24.8. 2021, mod. 20.8.24 @author: philippsen """ import numpy as np import control as ct import matplotlib.pyplot as plt plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['ps.fonttype'] = 42 T = 0.1 ; l = 0.5 ; g = 9.81 Am = np.array([[0, 1, 0, 0], [0, -1/T, 0, 0], [0, 0, 0, 1], [0, 1/(l*T), -g/l, 0]]) bm = np.array([[0],[ 1/T],[0],[-1/(l*T)]]) #cm = np.array([ 0, 1]) C = np.eye(4) # Falls alle Zustände ausgegeben werden sollen D = np.array([[ 0. ],[0],[0],[0]]) linKran = ct.ss(Am, bm, C, D) print('Pole : ',ct.poles(linKran)) # Zustandsreglerentwurf pol = np.array([-1,-1,-1,-1]) rr = ct.acker(Am,bm,pol*2.0) # nicht lineares Modell Kran def kran_update(t, x, u, params={}): # Reglerparameter übergeben, falls erforderlich kp = params.get('kp', 0.05) T1 = params.get('T1', 0.1) l = params.get('l', 0.5) # Zuweisung von Variablen und Zuständen vsoll = u[0] # Vorgabe v lage = x[0] # Zustand Lage v = x[1] # Zustand v = Lage punkt alpha = x[2] # Zustand alpha alphap = x[3] # Zustand erste Ableitung alpha # Berechnung Ableitungen lagep = v vp = -v/T1 + vsoll*kp/T1 alphapp = -np.sin(alpha)*9.81/l - vp*np.cos(alpha)/l # zweite Abl. alpha return [lagep, vp, alphap , alphapp] io_kran = ct.nlsys( kran_update, None, inputs=['u'], outputs=['lage','v','alpha','alphap'], states=['lage','v', 'alpha', 'alphap'], name='kran', params = { 'kp':1.0}) def x_rueck(t, x, u, params={}): # parameter übergeben, falls erforderlich vor = params.get('vor', 1) # Zuweisung von Variablen und Zuständen x0 = u[0]; x1 = u[1]; x2 = u[2]; x3 = u[3] # Rückführung berechnen später Skalarprodukt return rr[0,0]*x0 + rr[0,1]*x1 + rr[0,2]*x2 + rr[0,3]*x3 rueck = ct.nlsys( None, x_rueck, name='rueck', inputs = ['lage','v','alpha','alphap'], outputs = ['rue'], params = {'vor':1}) sumblk = ct.summing_junction(inputs=['w', '-rue'], output=['u']) #Regelkreis aufbauen Rk = ct.interconnect([io_kran, rueck, sumblk], inplist=['w'], outlist=['lage','alpha','u']) T = np.arange(0.0, 10.0, 0.01) # Simulationsdauer ww = np.ones([len(T)]) t, yy = ct.input_output_response(Rk, T, rr[0,0]*ww) #resp = control.input_output_response(Rk, T, ww) #rr[0,0]*ww) # Umrechnung rad Grad ur = 180/np.pi plt.figure(1) plt.plot(t,yy[0,:],t,ur*yy[1,:],t,yy[2,:]) plt.title('Kran mit Zustandsregler') plt.xlabel('t [s]'); plt.ylabel('lage, alpha, y') plt.grid(True)
web706
Modellreduktion mit balred()
Listing 7.6:
# -*- coding: utf-8 -*- """ Modellreduktion Standardregelstrecke Created on 4.1. 2022, mod. 20.8.24 @author: philippsen """ import numpy as np import control as ct import matplotlib.pyplot as plt plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['ps.fonttype'] = 42 g3 = ct.tf(1,[30, 31, 10, 1]) # Standardregelstrecke s3 = ct.tf2ss(g3) t, x = ct.step_response(g3) plt.figure(1) plt.plot(t,x) b2 = ct.balred(s3,2, method='matchdc') #b2 = balred(s3,2, method='truncate') # gb2 = ct.ss2tf(b2) print('G(s) = ',gb2) print(ct.poles(gb2)) t, xx = ct.step_response(b2,t) plt.plot(t,xx) plt.title('Standardregelstrecke und balred Ersatzmodell') plt.xlabel('t [s]') plt.ylabel('x') plt.grid() g2 = ct.tf(1,[25,10,1]) #Ersatzmodell 2. Ordnung T1=T2=5 t, xxx = ct.step_response(g2,t) plt.figure(2) plt.plot(t,x,t,xxx) plt.title('Standardregelstrecke und P-T2 Ersatzmodell') plt.xlabel('t [s]') plt.ylabel('x') plt.grid()