kramann.info
© Guido Kramann

Login: Passwort:










6.3 Erstellen eines Optimierers als modifiziertes Gradientenverfahren gemäß der Vorlage in Kapitel 5.4, Code 5.4-1

Simulator und Guetefunktion

  • Zwischenglied zwischen Gütefunktion und Integrator soll ein Simulator sein.
  • Dies ist ein Objekt, das eine Simulation mit vorgegebenen Parametersätzen durchführen kann und den neuen Verlauf der Zustandsgrößen liefert.
  • Neben den Zustandsgrößen wird in SimulatorPIDgeregelterAntrieb in einem Array x bei x0 auch die Regeldifferenz und bei x1 noch die Stellgröße pwm im zeitlichen Verlauf mit aufgezeichnet.
  • Im Optimierer kann dann ein Gütekriterium formuliert werden, in dem auch diese Größen ein Gewicht bekommen, um ein Übersteuern des Reglers zu vermeiden und um das Erreichen des Zielwertes gut verfolgen zu können.
  • Es wird an dieser Stelle darauf verzichtet auch SimulatorPIDgeregelterAntrieb und die zugehörige Basisklasse Simulator näher darzustellen, sondern nur bei der Erläuterung der Klasse "Fehlerfunktion", wo es erforderlich ist:
  • Da die Klasse Fehlerfunktion keine vorbereiteten Implementierungen für erbende Klassen enthält, kann sie gleich als Schnittstelle (Interface) implementiert werden:
package opti;
import java.awt.*; //package awt für die paint()-Methode nötig.
public abstract interface Fehlerfunktion
{
    public abstract double berechneFehler(double[] parameter);
    /** Fehlerfunktion kann durch Überschreiben der Methode paint() in die Lage
    versetzt werden, den aktuellen Fehlerverlauf grafisch darzustellen.<br/>
    Die Methode wird von der paint-Methode eines Canvas-Objekts her aufgerufen.
    */
    public abstract void paint(Graphics2D g);
}

Code 6.3-1: Schnittstelle Fehlerfunktion

  • Die folgende Umsetzung benutzt SimulatorPIDgeregelterAntrieb.
  • Unter Verwendung des beobachteten vom Simulator mit aufgezeichneten Verlaufs der Regeldifferenz und der Stellgröße wird der Fehler berechnet.
  • Insbesondere wird der Fehler größer, wenn das PWM-Stell-Signal außerhalb der Grenzen +/-1023 liegt.
  • Die Fehlerfunktion dient dazu, den PID-Regler für eine bekannte Regelstrecke zu beurteilen.
  • gewicht1 und gewicht2 können modifiziert werden, um die Fehlerarten Regelabweichung und PWM-Wert-Grenzüberschreitung unterschiedlich gewichten zu können.
package opti;
import java.awt.*; //package awt für die paint()-Methode nötig.
public class FehlerfunktionPIDgeregelterAntrieb implements Fehlerfunktion
{
    public Simulator simulator = null;
    /**Registrieren eines Simulators*/
    public void add(Simulator simulator)
    {
        this.simulator = simulator;
    }
    public double berechneFehler(double[] parameter)
    {
        double gewicht1=1.0,gewicht2=1.0;
        double fehler = 0;
        double P = parameter[0]; //z.B. 100
        double I = parameter[1]; //z.B. 10
        double D = parameter[2]; //z.B. 0
        simulator.init();
//ACHTUNG: K und L sind gegenüber der Scilab-Musterlösung in Kaptiel 5.6 vertauscht!
        simulator.setParameter(1576.1789,0); //K
        simulator.setParameter(11542.314,1); //L
        simulator.setParameter(372.33722,2); //M
        simulator.setParameter(P,3); //P
        simulator.setParameter(I,4); //I
        simulator.setParameter(D,5); //D
        simulator.setParameter(0.01,6); //Tt
        simulator.setParameter(20.0,7); //omega_viertel_soll
        simulator.simulieren();
        for(int i=0;i<simulator.getAnzahl();i++)
        {
            double e = (simulator.getX(i))[0];
            double pwm = (simulator.getX(i))[1];
            fehler += gewicht1*e;
            if(pwm>1023)
                fehler+=gewicht2*(double)(pwm-1023);
            if(pwm<-1023)
                fehler+=gewicht2*(double)(-pwm-1023);
        }
        return fehler;
    }
    /** paint(..) wird bei der Konsolenanwendung nicht verwendet.*/
    public void paint(Graphics2D g)
    {
    }
}

Code 6.3-2: FehlerfunktionPIDgeregelterAntrieb

  • Bei einem Optimierer-Objekt wird ein Fehlerfunktion-Objekt registriert, mit dem der aktuelle Fehler für einen Parametersatz berechnet wird.
  • Zu der nachfolenden Klasse gibt es eine Basisklasse Optimierer.java
package opti;
import java.awt.*; //package awt für die paint()-Methode nötig.
public class OptimiererModGrad extends Optimierer
{
    /**Optimierungsvorgang auslösen. Wird von ergbenden Klassen überschrieben*/
    public void optimieren()
    {
        /**Faktoren, mit denen die Sprungweite beim Ändern eines  Parameters
        variiert wird.*/
        double[] faktor = {-2.0,-1.0,-0.5,0.0,0.5,1.0,2.0};
        double[] testfehler = new double[7];
        /**Vektorlänge in die Suchrichtung*/
        double[] laenge = new double[anzahlParameter];
        for(int i=0;i<anzahlParameter;i++)
            laenge[i]=1.0;
        /**Fehler mit aktuellem Parametersatz bestimmen:*/
        double fehler = fehlerfunktion.berechneFehler(startparameter);
        double fehler_best = fehler;
        double fehler_akt = fehler;
        double[] neueparameter = new double[anzahlParameter];        
        for(int i=0;i<anzahlParameter;i++)
            neueparameter[i] = startparameter[i];
        boolean fertig = false;
        int imerk=0,kmerk=0;
        while(fertig==false)
        {
            //Fehler der Varianten bestimmen:
            for(int i=0;i<anzahlParameter;i++)
            {
                for(int k=0;k<faktor.length;k++)
                {
                    neueparameter[i]+=laenge[i]*faktor[k];
                    fehler_akt = fehlerfunktion.berechneFehler(neueparameter); 
                    if(fehler_akt<fehler_best)
                    {
                        imerk=i;
                        kmerk=k;
                        fehler_best = fehler_akt;
                    }
                    neueparameter[i]-=laenge[i]*faktor[k];
                }
            }
            neueparameter[imerk]+=laenge[imerk]*faktor[kmerk];                   
            //fehler_best = fehlerfunktion.berechneFehler(neueparameter);
            if(kmerk!=3)             
               laenge[imerk]*=faktor[kmerk]; /**Sprungweite verbessern für nächsten Schritt*/
            if(fehler_akt-fehler_best<epsilon)
                fertig = true;
            fehler_akt = fehler_best;
System.out.println("aktueller kleinster Fehler: "+fehler_akt);
        }
        System.out.println("Start-Parametersatz:");
        for(int i=0;i<anzahlParameter;i++)
        {
            System.out.println("Parameter Nr.0: "+startparameter[i]);
        }
        System.out.println("Startfehler: "+fehler);
        System.out.println("Minimierter Fehler: "+fehler_best);
        System.out.println("Bester gefundener Parametersatz:");
        for(int i=0;i<anzahlParameter;i++)
        {
            System.out.println("Parameter Nr.0: "+neueparameter[i]);
        }
    }
    /** paint(..) wird bei der Konsolenanwendung nicht verwendet.*/
    public void paint(Graphics2D g)
    {
    }
}

Code 6.3-3: OptimiererModGrad

  • Nachfolgendes Testprogramm liefert als optimierte Parameter:
  • P=22
  • I=6
  • D=2
package opti;
public class TestOptimiererModGrad
{
    public static void main(String[] args)
    {
        SimulatorPIDgeregelterAntrieb simulator = new SimulatorPIDgeregelterAntrieb();
        FehlerfunktionPIDgeregelterAntrieb fehlerfunktion = new FehlerfunktionPIDgeregelterAntrieb();
        fehlerfunktion.add(simulator);
        OptimiererModGrad optimierer = new OptimiererModGrad();
        optimierer.add(fehlerfunktion);
        optimierer.startparameter[0] = 100.0;
        optimierer.startparameter[1] = 10.0;
        optimierer.startparameter[2] = 0.0;
        optimierer.optimieren();
    }
}

Code 6.3-4: TestOptimiererModGrad

  • Mit den optimierten Parametern wurde mit folgendem Programm noch einmal eine Simulationdurchgeführt.
  • Es gibt auch die Regelabweichung und den Verlauf des PWM-Stellwertes mit aus.
  • Mit einem pipe-Befehl werden die Ausgabedaten in die Datei data_opti.txt geschoben und dann mit Scilab visualisiert.
  • Der Konsolenbefehl lautet dann: java opti/TestSimulatorPIDgeregelterAntrieb > data_opti.txt
package opti;
public class TestSimulatorPIDgeregelterAntrieb
{
    public static void main(String[] args)
    {
        SimulatorPIDgeregelterAntrieb simulator = new SimulatorPIDgeregelterAntrieb();
        simulator.simulationsschritte = 1000;
        simulator.init();
//ACHTUNG: K und L sind gegenüber der Scilab-Musterlösung in Kaptiel 5.6 vertauscht!
        simulator.setParameter(1576.1789,0); //K
        simulator.setParameter(11542.314,1); //L
        simulator.setParameter(372.33722,2); //M
//        simulator.setParameter(100.0,3); //P
//        simulator.setParameter(10.0,4); //I
//        simulator.setParameter(0.0,5); //D
        simulator.setParameter(22.0,3); //P
        simulator.setParameter(6.0,4); //I
        simulator.setParameter(2.0,5); //D
        simulator.setParameter(0.01,6); //Tt
        simulator.setParameter(20.0,7); //omega_viertel_soll
        simulator.simulieren();
        System.out.println("t/s  omega/(rad/s) e pwm");
        for(int i=0;i<simulator.getAnzahl();i++)
        {
            System.out.print(simulator.getT(i)+" "+(simulator.getY(i))[0]);
            System.out.println(" "+(simulator.getX(i))[0]+" "+(simulator.getX(i))[1] );
        }
    }
}

Code 6.3-5: TestSimulatorPIDgeregelterAntrieb - Testsimulation mit optimierten Regelparametern.

Mit Scilab erzeugte Kurven zu einem Simulationslauf mit P=22, I=6, D=2.

Bild 6.3-1: Mit Scilab erzeugte Kurven der Java basierten Simulation mit P=22, I=6, D=2.

optimierung.zip - Download der oben beschriebenen Programme.
Übung
  • Testen Sie die von Ihnen durch Optimierung und/oder Tests gefundenen Parameter mit TestSimulatorPIDgeregelterAntrieb.
  • Stellen Sie geeignete Klassen aus der Java-Simulationsumgebung für die Identifikation der Regelstrecke (Antrieb) zusammen, tragen Sie die passende Totzeit ein und führen die Identifizierung durch.
  • Falls Sie keine geeignete Datengundlage haben, finden Sie nachfolgend Beispieldaten zweier Projektgruppen.

projektwoche.zip - Download einiger Ergebnisdaten der Projektwoche.

autogui.zip - Aktueller Stand der Java-Simulationsumgebung.

Beispiel

Mit Scilab erzeugte Kurven zu einem Simulationslauf mit P=22, I=6, D=2.

Bild 6.3-2: Mit Scilab erzeugte Kurven der Java basierten Simulation mit P=70, I=30, D=10, Datenbasis Projektwoche_Gruppe3_jentsch.zip, "erfühlte Parameter."