我以前使用Ziegler方法调整PID控制器的参数来控制机器人的位置。然后,我实现了模糊逻辑以自我调整参数。
我有两个模糊逻辑控制器输入;一个是位置误差和错误率。

我知道我的问题可能是由于不太了解每个参数的影响。

问题是我在建立模糊规则时感到困惑。什么时候需要对Kp,Kd和Ki使用高值和低值来实现最佳调整?当误差几乎为零时,Kp是否必须非常低(因此,机器人处于所需位置)?同一问题适用于所有三个参数。

评论

很抱歉这个问题,但是如果您使用的是模糊逻辑,为什么不只使用它来制作模糊逻辑控制器呢?它比PID具有更强大的功能,并且可以处理非线性。

您能画出一个图表来显示如何连接传感器,执行器,PID和模糊逻辑系统吗?为什么PID不够好,无法控制机器人的位置?

您能提供参考的acspid源代码吗?

#1 楼

E. Abbasi,M. J. Mahjoob在论文中使用模糊系统在悬停模式下调整PID增益使用模糊系统控制四旋翼无人机,解释了如何使用模糊逻辑调整PID增益。您可以找到许多有关单例调整的论文,但本文显示了完全模糊控制


使用齐格勒-尼古尔斯(或其他技术)查找PID增益具有输入错误(e)和错误更改(de)

定义输入和输出的模糊化图。定义限制(也可以更改形状),如

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]


创建规则如
/> if **e** and/or **de** *fuzzyname* (small,big etc.) than KI is fuzzyname (small,big etc.)

对结果进行模糊处理。 -PID只需将质量更改为e,将服务更改为de,最后您可以将小费输出更改为KP / KI / KD
(有关于小费问题的示例:python scikit Fuzzy-模糊控制系统:小费问题) />
注1:错误范围应明确定义,因此必须记录错误并更改错误。限制必须在这些值的最大值和最小值中。

注2:输出值范围在-1和1之间。

Fuzzy-PID的示例代码python中的代码在这里:

# -*- 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)


模糊输入成员函数:


模糊输出成员函数:


状态:在状态图中,虚线是目标值,红色线是PID,绿色线是Fuzzy-PID

此处为acspid类

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




评论


$ \ begingroup $
仅链接的答案无法提供对该方法的任何了解。如果您可以总结文章,将会很有帮助。
$ \ endgroup $
– Paul
16-11-28在19:28



$ \ begingroup $
@Paul,够了吗?
$ \ endgroup $
–acs
16-11-28在20:26



$ \ begingroup $
感谢@acs的全面答复。但是,在链接时,请尽量避免使用本文或类似的链接文本。链接容易腐烂,如果发生这种情况,则链接文本不会帮助任何人找到该页面。通常丢失的页面没有被删除,它们只是被移到了另一个位置。如果您将页面标题(以及论文的作者)作为链接文本给出,则对该文本的搜索通常会找到新的位置。
$ \ endgroup $
– Mark Booth♦
16年11月29日在11:16

$ \ begingroup $
@acs在上面的python代码(Fuzzy-PID)中,有一个名为(acspid)的导入库,没有它,代码无法实现。您能证明还是请展示一下,谢谢。
$ \ endgroup $
–艾哈迈德·费萨尔(Ahmed Faisal)
19年1月20日在22:36



$ \ begingroup $
@AhmedFaisal很抱歉未能及时回答。我添加了acspid类。
$ \ endgroup $
–acs
19年1月24日在20:24