Wie kann ich die PID-Parameter mit Fuzzy Logic einstellen?

7

Ich habe zuvor die Ziegler-Methode verwendet, um die Parameter meines PID-Reglers so einzustellen, dass die Position meines Roboters gesteuert wird. Ich habe dann Fuzzy-Logik zur Selbstoptimierung der Parameter implementiert. Ich habe zwei Eingänge zum Fuzzy-Logik-Controller; Einer ist der Positionsfehler und die Fehlerrate.

Ich weiß, dass mein Problem möglicherweise darin besteht, dass ich die Auswirkungen der einzelnen Parameter nicht sehr gut verstehe.

Das Problem ist, dass ich beim Einrichten der Fuzzy-Regeln verwirrt bin. Wann muss ich hohe und niedrige Werte für Kp, Kd und Ki verwenden, um die beste Abstimmung zu erzielen? Muss Kp sehr niedrig sein, wenn der Fehler fast Null ist (daher befindet sich der Roboter an der gewünschten Position)? Die gleiche Frage gilt für alle drei Parameter.

Moayad Hani Abu Rmilah
quelle
Entschuldigen Sie die Frage, aber wenn Sie mit Fuzzy-Logik arbeiten, warum verwenden Sie sie nicht einfach, um einen Fuzzy-Logik-Controller zu erstellen? Es ist viel leistungsfähiger als eine PID und kann Nichtlinearitäten verarbeiten.
Goncalo Luis
1
Können Sie ein Diagramm zeichnen, das zeigt, wie Ihre Sensoren, Aktoren, PID- und Fuzzy-Logik-Systeme verbunden sind? Warum war die PID nicht gut genug, um die Position Ihres Roboters zu kontrollieren?
Ian
Könnten Sie acspid Quellcode für die Referenz bereitstellen? Vielen Dank im Voraus.
David

Antworten:

9

In dem Artikel Controlling of Quadrotor UAV unter Verwendung eines Fuzzy-Systems zum Einstellen der PID-Verstärkungen im Schwebemodus von E. Abbasi erklärt MJ Mahjoob , wie PID-Verstärkungen mit Fuzzy-Logik eingestellt werden. Sie können viele Artikel über Singleton-Tuning finden, aber dieser Artikel zeigt eine völlig unscharfe Kontrolle

  1. Finden Sie PID-Gewinne mit Ziegler-Nichols (oder einer anderen Technik)
  2. Erstellen Sie einen Fuzzy-PID-Verstärkungswechsler mit Eingangsfehler (e) und Fehleränderung (de).
  3. Definieren Sie Fuzzifizierungsdiagramme für Ein- und Ausgänge. Definieren Sie Grenzen (Sie können auch die Form ändern) wie

    name [min,peak,max]

    very small [-1,-1,-0.6], small [-1,-0.6,0], medium [-0.6,0,0.6], big [0,0.6,1], very big [0.6,1,1]

  4. Regeln erstellen wie

    if **e** and/or **de** *fuzzyname* (small,big etc.) than KI is fuzzyname (small,big etc.)

  5. Defuzzyfy das Ergebnis.

Sie können Tools wie matlab fuzzy toolbox oder python skfuzzy verwenden

Das Trinkgeldproblem kann als Fuzzy-PID verwendet werden. Ändern Sie einfach die Qualität als e und den Service als de. Zuletzt können Sie die Trinkgeldausgabe als KP / KI / KD ändern (es gibt ein Beispiel für das Trinkgeldproblem: Python Scikit Fuzzy - Fuzzy Control Systems: Das Trinkgeld Problem )

Hinweis 1: Fehlerbereiche sollten gut definiert sein, daher müssen Sie den Fehler protokollieren und den Fehler ändern. Die Grenzwerte müssen in Max- und Min-Werten dieser Werte liegen

Hinweis 2: Der Ausgabewertbereich liegt zwischen -1 und 1.

Ein Beispielcode für Fuzzy-PID in Python ist hier:

# -*- coding: utf-8 -*-
"""
@author: acs
"""

import skfuzzy as fuzz
from skfuzzy import control as ctrl
import acspid
import numpy as np
from matplotlib import pyplot as plt

plt.ion()
fig=plt.figure()

ferr = ctrl.Antecedent(np.arange(-150, 150, 1), 'ferr')
fder = ctrl.Antecedent(np.arange(-150, 150, 1), 'fder')
fout = ctrl.Consequent(np.arange(-1, 1, 0.01), 'fout')

ferr.automf(5)
fder.automf(5)
fout.automf(5)
fout['poor'] = fuzz.trimf(fout.universe, [-1, -1, -0.5])
fout['mediocre'] = fuzz.trimf(fout.universe, [-1, -0.5, 0])
fout['average'] = fuzz.trimf(fout.universe, [-0.1, 0, 0.1])
fout['decent'] = fuzz.trimf(fout.universe, [0, 0.5, 2])
fout['good'] = fuzz.trimf(fout.universe, [0.5, 1, 1])
fout.view()
ferr.view()
fder.view()
plt.show()
plt.pause(0.0001)

#'poor'; 'mediocre'; 'average'; 'decent', or 'good'
rules=[]
rules.append(ctrl.Rule(ferr['average'] | fder['average'] , fout['average']))
rules.append(ctrl.Rule(ferr['decent'] | fder['decent'] , fout['decent']))
rules.append(ctrl.Rule(ferr['good'] | fder['good'] , fout['good']))
rules.append(ctrl.Rule(ferr['mediocre'] | fder['mediocre'] , fout['mediocre']))
rules.append(ctrl.Rule(ferr['poor'] | fder['poor'] , fout['poor']))

fctrl = ctrl.ControlSystem(rules)
fpid = ctrl.ControlSystemSimulation(fctrl)

pid=acspid.pidcont(1.2,0.02,0.01,5,-5)

pid2=acspid.pidcont(1.2,0.02,0.01,5,-5)

d=np.zeros(10)
for i in range(10):
    d=np.append(d,np.ones(10)*np.random.uniform(-100,100,1))

print len(d)
m=[]
m.append(0.0)
m2=[]
m2.append(0.0)
e=[]
de=[]
e2=[]
de2=[]

kp=pid.kp
kd=pid.kd
ki=pid.ki
for i in range(len(d)):
    pid.setDesired(d[i])
    print "e:",pid.error ,"\t de:", pid.ed
    fpid.input['ferr'] = pid.error
    fpid.input['fder'] = pid.ed
    fpid.compute()
    newpid=np.abs(fpid.output['fout'])
    print "PID:", newpid*pid.kp,"\t",newpid*pid.ki,"\t",newpid*pid.kd
    pid.setGains(newpid*kp,newpid*ki,newpid*kd)
    newm=pid.update(m[-1])
    newm=m[-1]+newm
    print i,m[-1],newm
    m.append(newm)
    e.append(pid.error)
    de.append(pid.ed)

    pid2.setDesired(d[i])
    newm2=pid2.update(m2[-1])
    newm2=m2[-1]+newm2
    m2.append(newm2)
    e2.append(pid2.error)
    de2.append(pid2.ed)

    ax1 =plt.subplot(2,1,1)
    ax1.set_xlim([0, len(d)])
    ax1.set_ylim([-200, 200])
    plt.grid()
    plt.plot(range(len(m)),m,linewidth=5.0)
    plt.plot(range(len(m2)),m2,linewidth=2.0)
    plt.plot(range(len(d)),d,'g--')

    plt.title('Status')
    ax2=plt.subplot(2,1,2)
    ax2.set_xlim([0, 50])
    ax2.set_ylim([-100, 100])
    plt.plot(range(len(e)),e,'r-',range(len(de)),de,'g-')
    plt.grid()
    plt.title('e and ed')
    #plt.draw()
    plt.show()
    plt.pause(0.0001)

Fuzzy-Eingangsmitgliedschaftsfunktionen: Geben Sie hier die Bildbeschreibung ein

Fuzzy-Ausgabe Mitgliedschaftsfunktion: Geben Sie hier die Bildbeschreibung ein

Status: Im Statusdiagramm ist die gestrichelte Linie der Zielwert, die rote Linie die PID und die grüne Linie die Fuzzy-PID

Hier die acspid Klasse

class pidcont():
    def __init__(self,P,I,D,pmax,pmin):
        self.kp=P
        self.kd=D
        self.ki=I
        self.pidmax=pmax
        self.pidmin=pmin
        self.desired=0.0
        self.error=0.0
        self.elast=0.0
        self.esum=0.0
        self.eder=0.0
    def update(self,current):
        self.error=self.desired-current
        self.eder=self.error-self.elast
        self.elast=self.error
        self.esum=self.esum+self.error
        if self.esum>self.pidmax:
            self.esum=self.pidmax
        elif self.esum<self.pidmin:
            self.esum=self.pidmin

        self.P=self.kp*self.error
        self.D=self.kd*self.eder
        self.I=self.ki*self.esum
        pid=self.P+self.I+self.D
        return pid
    def setDesired(self,d):
        self.desired=d
    def setGains(self,P,I,D):
        self.kp=P
        self.kd=D
        self.ki=I
    def setLimits(self,pmax,pmin):
        self.pidmax=pmax
        self.pidmin=pmin

Geben Sie hier die Bildbeschreibung ein

acs
quelle
Nur-Link-Antworten bieten keinen Einblick in die Methode. Es wäre hilfreich, wenn Sie stattdessen den Artikel zusammenfassen könnten.
Paul
2
@ Paul, ist das genug?
ACs
2
Vielen Dank für eine umfassende Antwort @acs. Vermeiden Sie beim Verknüpfen jedoch die Verwendung dieses Dokuments oder eines ähnlichen Dokuments als Linktext. Links neigen dazu zu verrotten und wenn dies passiert, hilft der Linktext niemandem, die Seite zu finden. Oft wurden fehlende Seiten nicht entfernt, sondern nur an einen anderen Ort verschoben. Wenn Sie den Seitentitel (und die Autoren eines Papiers) als Linktext angeben, wird bei der Suche nach diesem Text häufig der neue Speicherort gefunden.
Mark Booth
1
@acs im obigen Python-Code (Fuzzy-PID) gibt es eine importierte Bibliothek mit dem Namen (acspid), der Code ist ohne ihn nicht implementiert. Könntest du es beweisen oder zeigen, bitte, danke.
Ahmed Faisal
@ AhmedFaisal Entschuldigung für die späte Antwort. Ich habe die acspid-Klasse hinzugefügt.
ACs