模糊控制-模糊性知识的应用问题

30 篇文章 1 订阅
25 篇文章 0 订阅

上篇文章谈了模糊性知识的表示问题,这篇文章就来谈谈模糊性知识的应用问题。

在上篇文章中,我们说到,模糊性知识由三部分组成:

  • 用于表示人类如何进行判断的产生式规则,形如:如果…则…

  • 用于说明我们所了解到的事实的模糊命题,如:速度 是 大

  • 用于确定模糊量取值的隶属度定义,如:实际测得的数值是123,而123算做大的可能性是0.8,算做正常的可能性是0.5,算做小的可能性是0.3,

根据人类思考、解决问题的一般模式,结合模糊性知识的组成,其应用实际上可以分解为三个过程:

  • 对真实世界的理解过程:我们从真实世界能获取到的是各种传感器所采集到的各种输入信号,这个理解过程,就是用模糊量各取值的隶属度定义来确定某个输入信号对应某模糊量各个取值的隶属度,确定所有输入信号对应各个模糊量取值的隶属度,也就是完成了模糊系统对真实世界的理解,比如:车速是快、方向是非常左、汽油是有点少。对于模糊系统来说,这个过程就是对实际采集到的确切的精确数据进行模糊化的过程

  • 运用人类经验进行结果判断的推理过程:根据模糊量各取值的可能性来计算各条模糊规则的有效性,最后综合所有有效规则得到对结果的综合判断,这一过程其实就是根据各个模糊规则对所了解到的事实进行模糊推理以确定各种结果的可能性

  • 推理结果的解释过程:推理过程得到的是一组模糊量的各种取值的可能性,所以结果的解释过程其实就是对推理所得到的那些个大小快慢的定性判断转换为250这样清晰的数字量,才能发送给执行器进行执行。模糊推理得到的是各种取值的可能性,本身也就是一个模糊集合,这个过程就是将这个模糊集合解模糊为真实世界中的某个具体的数据

还是一头雾水吧?嗯,换种说法再来一遍:

  • 理解过程,比如测得面盆里的面的含水量是70%,然后根据水多水少的隶属度进行计算,最后得到,这个70%的含水量,算做水多的可能性是0.8,算做水少的可能性是0.3888。嗯,那为什么水多的可能性是0.8啊?!哼,上篇文章说了:随我啊。我说它就是0.8:) 这就叫主观(我是根据自己天天和200斤面的经验认为的)、先验(算前就得给,给了你就得信,你不服就天天和个1000斤面吧),合起来就是:这个隶属度我认为是多少它就是多少:) 这个隶属度怎么给就体现了我们的经验

  • 推理过程,根据水多了加面这条规则,我算出来的结果是:加面少许。同时需要给出这个少经过计算的隶属度函数,由于只有这一条规则起作用,所以结果就是加面少许,如果有多个规则起作用,可能最后的计算结果是几条:加面少许(0.8)、正常加面(0.4)、拼命加面(0.1)等等,然后这每个结果都有个有效性,就象圆括号里面的0.8、0.4之类的

  • 解释过程,就是对推理过程所输出的加面少许(0.8)、正常加面(0.4)、拼命加面(0.1)等进行综合计算,根据对面多面少的隶属度的定义,一通算,最后算出来的结果是:123.456,这时就可以把这个123.456发送给执行器去抖啊抖的抖进面盆里123.456克面粉了

说起来是不是很难以理解?嗯,其实这都是基于模糊数学的计算,如果你由于对模糊系统暂时还不太理解,其实也不会影响你使用模糊控制的:在PythonPi平台上,只要你完成了模糊知识系统的定义工作,在实际应用时,只需要简单的送入各个输入传感器所采集到的数据并请求模糊系统进行推理,然后取出经过解释的推理结果直接发送给执行器就OK啦:)

PythonPi平台所采用的模糊系统其特性为:单值模糊器、乘法推理机、中心平均解模糊器。这主要是出于简化未来通过自学习构造模糊规则库的考虑

好的,我们先来展示一下在PythonPi平台上,用模糊控制功能实现的基于人脸检测的小车行车控制是怎么做的吧:

from cn.ijingxi.corpuscle.python import webApp
from cn.ijingxi.corpuscle.python import car
from cn.ijingxi.corpuscle.python import active
from cn.ijingxi.corpuscle.python import input
from cn.ijingxi.corpuscle.python import fuzzyControl
from cn.ijingxi.intelControl.python import jxpy
import math

#设置初始变量
stoped=False
pi2=math.pi/2.0
pi8=math.pi/8.0
pi16=math.pi/16.0
pier=math.pi/72.0

#左车轮的控制动作
leftEN=active.getPWM("/pi1/15")
leftIn1_high=active.getGPIO("/pi1/16",active.HIGH)
leftIn1_low=active.getGPIO("/pi1/16",active.LOW)
leftIn2_high=active.getGPIO("/pi1/1",active.HIGH)
leftIn2_low=active.getGPIO("/pi1/1",active.LOW)
#右车轮的控制动作
rightEN=active.getPWM("/pi1/8")
rightIn1_high=active.getGPIO("/pi1/9",active.HIGH)
rightIn1_low=active.getGPIO("/pi1/9",active.LOW)
rightIn2_high=active.getGPIO("/pi1/7",active.HIGH)
rightIn2_low=active.getGPIO("/pi1/7",active.LOW)
#小车的控制信号
#启停
iswitch=input.get("/pi1/faceCar")
#方向角
iradian=input.get("/pi1/faceCar_radian")
#速度
ipower=input.get("/pi1/faceCar_power")

#小车的定义
c=car("myCar")
#左车轮的控制
c.addLeftWheel(leftIn1_high,leftIn1_low,leftIn2_high,leftIn2_low,leftEN)
#右车轮的控制
c.addRightWheel(rightIn1_high,rightIn1_low,rightIn2_high,rightIn2_low,rightEN)
#启停、方向角、速度的控制
c.addInputSignal(iswitch,iradian,ipower)

#模糊控制
fuzzy=fuzzyControl()

#模糊知识库的定义,包括模糊量的定义和模糊规则的定义
#模糊量
#视频捕获到的人脸水平中心所在位置,整个视频的大小是1024×768,所以人脸居中,就是人脸的中心点在512处
#左的定义:从0-128肯定是左,从128-256是从1到0.7依次降低,而从256-512是从0.7到0的折线
fuzzy.addValue("水平","左",128.0,{},{256.0:0.7,512.0:0.0})
fuzzy.addValue("水平","居中",512.0,{388.0:0.0,450.0:0.7},{574.0:0.7,636.0:0.0})
fuzzy.addValue("水平","右",896.0,{512.0:0.0,768.0:0.7},{})
fuzzy.addValue("水平","好",512.0,{507.0:0.0},{517.0:0.0})
#视频捕获到的人脸距离,以人脸高进行判断
fuzzy.addValue("距离","远",20.0,{},{100.0:0.7,125.0:0.0})
fuzzy.addValue("距离","居中",120.0,{100.0:0.0,110.0:0.7},{160.0:0.0,130.0:0.7})
fuzzy.addValue("距离","近",240.0,{115.0:0.0,160.0:0.7},{})
fuzzy.addValue("距离","居中",120.0,{115.0:.0},{125.0:0.0})
#小车速度,由于1.5秒才能识别一次人脸,如果太快则来不及进行下一次控制小车就会跑出画面;但如果太慢,小车根本就开不动
fuzzy.addValue("速度","快",40.0,{30.0:0.0},{})
fuzzy.addValue("速度","正好",30.0,{27.0:0.0},{33.0:0.0})
fuzzy.addValue("速度","慢",20.0,{},{30.0:0.0})
#小车方向,包括前进和后退
fuzzy.addValue("方向","大幅右退",pi2+pi8+pi16,{pi2+pi8:0.7,pi2:0.0},{})
fuzzy.addValue("方向","右退",pi2+pi8,{pi2+pi16:0.7,pi2:0.0},{})
fuzzy.addValue("方向","退",pi2,{pi2-pier:0.0},{pi2+pier:0.0})
fuzzy.addValue("方向","左退",pi2-pi8,{},{pi2-pi16:0.7,pi2:0.0})
fuzzy.addValue("方向","大幅左退",pi2-pi8-pi16,{},{pi2-pi8:0.7,pi2:0.0})

fuzzy.addValue("方向","大幅右进",-pi2-pi8-pi16,{},{-pi2-pi8:0.7,-pi2:0.0})
fuzzy.addValue("方向","右进",-pi2-pi8,{},{-pi2-pi16:0.7,-pi2:0.0})
fuzzy.addValue("方向","进",-pi2,{-pi2-pier:0.0},{-pi2+pier:0.0})
fuzzy.addValue("方向","左进",-pi2+pi8,{-pi2+pi16:0.7,-pi2:0.0},{})
fuzzy.addValue("方向","大幅左进",-pi2+pi8+pi16,{-pi2:0.0,-pi2+pi8:0.7},{})

#为了简化编程,便于使用,我们采用了用汉语表达式的形式来描述模糊规则
#模糊规则,非常是限定词,非常左,可以理解为左了再左,隶属度是左的平方
#这里的模糊规则其实就是我们觉得小车在各个区域时应该如何走才能让人脸逼近目标区域
#了解了小车的控制原理之后,画个示意图分划下不同区域就可以很容易的得出控制规则,然后投入运行进行调整,很快就完成了:)
fuzzy.addRule("如果 水平 是 非常 左 且 距离 是 非常 近 则 速度 是 快 且 方向 是 退")
fuzzy.addRule("如果 水平 是 左 且 距离 是 非常 近 则 速度 是 慢 且 方向 是 大幅左退")
fuzzy.addRule("如果 水平 是 左 且 距离 是 近 则 速度 是 正好 且 方向 是 左退")
fuzzy.addRule("如果 水平 是 居中 且 距离 是 近 则 速度 是 慢 且 方向 是 退")
fuzzy.addRule("如果 水平 是 右 且 距离 是 近 则 速度 是 正好 且 方向 是 右退")
fuzzy.addRule("如果 水平 是 右 且 距离 是 非常 近 则 速度 是 慢 且 方向 是 大幅右退")
fuzzy.addRule("如果 水平 是 非常 右 且 距离 是 非常 近 则 速度 是 快 且 方向 是 退")

fuzzy.addRule("如果 水平 是 非常 左 且 距离 是 非常 远 则 速度 是 慢 且 方向 是 大幅左进")
fuzzy.addRule("如果 水平 是 左 且 距离 是 非常 远 则 速度 是 正好 且 方向 是 左进")
fuzzy.addRule("如果 水平 是 左 且 距离 是 远 则 速度 是 慢 且 方向 是 左进")
fuzzy.addRule("如果 水平 是 居中 且 距离 是 远 则 速度 是 慢 且 方向 是 进")
fuzzy.addRule("如果 水平 是 右 且 距离 是 远 则 速度 是 正好 且 方向 是 右进")
fuzzy.addRule("如果 水平 是 右 且 距离 是 非常 远 则 速度 是 正好 且 方向 是 右进")
fuzzy.addRule("如果 水平 是 非常 右 且 距离 是 非常 远 则 速度 是 慢 且 方向 是 大幅右进")

#设置一个目标,当该目标达成时模糊控制系统会执行指定的完成通知函数
fuzzy.setTarget("水平 是 好 且 距离 是 好")

#模糊推理后的推理结果通知函数
def drive():
    #获取模糊系统推出的方向值
    fx=fuzzyControl.getRealValue("方向")
    #发送给执行器执行
    iradian.trigger(fx)
    #获取模糊系统推出的速度值
    sd=fuzzyControl.getRealValue("速度")
    #发送给执行器执行
    ipower.trigger(math.floor(sd))

#目标达成时的通知函数
def conclude():
    global stoped
    #停止继续接收人脸检测的结果
    stoped=True
    #停车
    iswitch.trigger(active.HIGH)

#检测到人脸后的执行函数
def receiveFace(face):
    if stoped:
        return
    #推理过程中唯一需要做的事情就是用实时采集到的输入数据来更新系统状态
    fuzzyControl.setRealValue("水平",face.x+face.width/2)
    fuzzyControl.setRealValue("距离",face.height)
    #开始模糊推理,如果达到目标值则执行conclude函数,否则将调用drive函数
    #推理结束后,模糊系统会自动更新速度和方向的实际数值
    fuzzy.presume("drive","conclude")

#开始人脸检测,当检测到人脸后执行receiveFace函数,并将检测到的人脸发送给receiveFace函数
c.startFaceDetect("receiveFace")

#定义一个webApp
w=webApp.get("RemoteControlCar")

#在webApp中添加树莓派摄像头输出
w.addVideo1("myVideo",True)

#设置该应用为默认应用
w.setDefaultApp("RemoteControlCar")

====================================================================================================

关注我的公众号及时获取推送的最新文章

公众号

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值