Verknüpfung des Antriebs mit einem Fuzzy-Regler und Simulation.
Nun soll der Antrieb aus Kapitel 6.1 mit einem passenden Fuzzy-Regler versehen werden.
Zunächst werden Modell und Simulator ohne Regler bereitgestellt:
Bereitstellen von Antriebs-Modell und Simulator ohne Regler:
- Eine passende Simulation steht bereit in Form des Programms TestAntrieb.java, bzw. Antrieb.java im Package opti.
- Mit dem Skript starten.bat kann das Programm kompiliert, gestartet und das Ergebnis in Scilab angeschaut werden.
- Nachfolgend kann dieses Beispiel heruntergeladen werden:
|
antrieb2.zip - Stellt u.a. ein noch ungeregeltes Simulationsmodell für den Antrieb bereit.
package opti;
import java.awt.*;
public class Antrieb extends Simulationsmodell
{
/**
Die folgenden Variablen sind die Modellparameter, die später
optimiert werden können.
Als Startwert sind die zu erwartenden Extremwerte eingestellt, damit
später automatisiert GUI-Elemente erzeugt werden können.
Da positive Extremwerte vorgegeben sind, ist damit festgelegt, dass
alle Modell-Parameter nicht negativ werden dürfen.
*/
//ACHTUNG: K und L sind gegenüber Scilab-Musterlösung vertauscht!
public double K = 100000.0;
public double L = 100000.0;
public double M = 100000.0;
public double pwm = -1023.0;
public Antrieb()
{
super(2); //Zwei Simulationsgleichungen
}
public double[] berechneRechteSeite(double[] yalt, double t)
{
/**Eigentliche Bestimmung der rechten Seite (Steigungsvektor)*/
f[0] = yalt[1];
f[1] = - K*yalt[1] - L*yalt[0] + M*pwm;
return f;
}
/** paint(..) wird bei der Konsolenanwendung nicht verwendet.*/
public void paint(Graphics2D g)
{
}
}
Code 0-1: Klasse Antrieb
package opti;
public class TestAntrieb
{
public static void main(String[] args)
{
Antrieb antrieb = new Antrieb();
RungeKuttaIntegrator rungekuttaintegrator = new RungeKuttaIntegrator();
rungekuttaintegrator.add(antrieb);
//ACHTUNG: K und L sind gegenüber der Scilab-Musterlösung in Kaptiel 5.6 vertauscht!
antrieb.K=1576.1789;
antrieb.L=11542.314;
antrieb.M=372.33722;
antrieb.pwm = 1023.0;
double dt = 0.001;
double t = 0.0;
double[] y;
double[] yalt = {0.0,0.0};
for(int i=0;i<473;i++)
{
System.out.println(t+" "+yalt[0]);
y = rungekuttaintegrator.zeitschritt(yalt,t,dt);
yalt[0] = y[0];
yalt[1] = y[1];
t+=dt;
}
}
}
Code 0-2: Klasse TestAntrieb
Entwurf des Fuzzy-Reglers
- An der Simulation der Sprungantwort ist zu sehen, dass maximal 30 erreicht wird (Einheit Omega/4).
- Also wird als Sollwert 20 vorgegeben.
- Der Fuzzy-Regler soll einfach aufgebaut werden:
- Eingangsgröße soll nur die Regelabweichung e sein, Ausgangsgröße das PWM-Signal.
- Die Fuzzy-Sets werden folgendermaßen entworfen:
|
- Fuzzy-Eingangsgröße: E mit den Ausprägungen:
- ENG - Regeldifferenz negativ groß
- ENK - Regeldifferenz negativ klein
- ENN - Regeldifferenz quasi Null
- EPK - Regeldifferenz positiv klein
- EPG - Regeldifferenz positiv groß
|
- Fuzzy-Ausgangsgröße: P mit den Ausprägungen:
- PNG - PWM negativ groß
- PNK - PWM negativ klein
- PNN - PWM quasi Null
- PPK - PWM positiv klein
- PPG - PWM positiv groß
|
- E wird zunächst im Intervall +/-10 gleichverteilt.
- P wird zunächst im Intervall +/-1023 gleichverteilt.
- Intuitiv erstellte Fuzzy-Regeln:
|
- WENN ENG DANN PNG
- WENN ENK DANN PNK
- WENN ENN DANN PNN
- WENN EPK DANN PPK
- WENN EPG DANN PPG
|
- Um die Programmstruktur möglichst unverändert zu lassen, wird die Klasse Antrieb direkt mit dem Fuzzy-Regler versehen.
- Die Klassen der Fuzzy-Regelung werden noch vorher in ein Package mit Namen fuzzy gelegt (s. antrieb3.zip).
|
package opti;
import java.awt.*;
import fuzzy.*; //Fuzzy-Package importieren.
public class Antrieb extends Simulationsmodell
{
public double K = 100000.0;
public double L = 100000.0;
public double M = 100000.0;
public double pwm = -1023.0;
//Fuzzy-Regler einfügen:
FuzzyRegler fuzzyregler = null;
private double[] e_aktuell = new double[1];
public Antrieb()
{
super(2); //Zwei Simulationsgleichungen
//Fuzzy-Regler initialisieren:
//1. Fuzzy-Regler erstellen:
fuzzyregler = new FuzzyRegler();
//2. Fuzzy-Eingangs-Sets erstellen:
FuzzyEingangsSet[] fes = new FuzzyEingangsSet[1];
FuzzyEingangsSet regeldifferenz = new FuzzyEingangsSet();
regeldifferenz.erzeugeFuzzyGroessen(5);
regeldifferenz.verteileFuzzyGroessenGleichmaessig(-10.0,10.0);
fes[0] = regeldifferenz;
fuzzyregler.setFuzzyEingangsSet(fes);
//3. Fuzzy-Ausgangs-Set erstellen:
FuzzyAusgangsSet fas = new FuzzyAusgangsSet();
fas.erzeugeFuzzyGroessen(5+2); //Fünf Fuzzygrößen und Minimum und Maximum
fas.verteileFuzzyGroessenGleichmaessig(-1023.0,1023.0);
fuzzyregler.setFuzzyAusgangsSet(fas);
//4. Fuzzy-Regeln hinzufügen:
int[][] regeln = new int[5][];
regeln[0] = new int[] {0, 0,0};//WENN ENG DANN PNG
regeln[1] = new int[] {1, 0,1};//WENN ENK DANN PNK
regeln[2] = new int[] {2, 0,2};//WENN ENN DANN PNN
regeln[3] = new int[] {3, 0,3};//WENN EPK DANN PPK
regeln[4] = new int[] {4, 0,4};//WENN EPG DANN PPG
fuzzyregler.setFuzzyRegeln(regeln);
}
public double[] berechneRechteSeite(double[] yalt, double t)
{
/**Eigentliche Bestimmung der rechten Seite (Steigungsvektor)*/
e_aktuell[0] = 20.0 - yalt[0];
pwm = fuzzyregler.berechneAusgang(e_aktuell);
f[0] = yalt[1];
f[1] = - K*yalt[1] - L*yalt[0] + M*pwm;
return f;
}
/** paint(..) wird bei der Konsolenanwendung nicht verwendet.*/
public void paint(Graphics2D g)
{
}
}
Code 0-3: Modifizierte Klasse Antrieb mit Fuzzy-Regler.
- Bei den anfänglichen Einstellungen ergibt sich folgender Verlauf:
|
Bild 0-1: Verlauf bei den intuitiv gewählten Fuzzy-Regeln.
antrieb3.zip - Antrieb mit Fuzzy-Regler.