精华内容
下载资源
问答
  • tp php 获取控制器控制器方法

    万次阅读 2020-07-06 10:15:12
    php 权限控制器等获取 php 获取文件名(获取控制器,通过读目录的方式) $planPath = APP_PATH.$modules[$type]['name'].'/controller'; $planList = array(); $dirRes = opendir($planPath); while($dir = readdir($...

    php 权限控制器等获取

    php 获取文件名(获取控制器,通过读目录的方式)

    $planPath = APP_PATH.$modules[$type]['name'].'/controller';
    $planList = array();
    $dirRes = opendir($planPath);
    while($dir = readdir($dirRes))
    {
    	if(!in_array($dir,array('.','..','.svn')))
    	{
    		$planList[] = basename($dir,'.php');
    	}
    }
    

    thinkphp 获取类对象里的方法名

    $control = 'index';
    $className = "app\\admin\\controller\\".$control;
    // ReflectionClass PHP内置函数,不懂的自己查手册
    $methods = (new \ReflectionClass($className))->getMethods(\ReflectionMethod::IS_PUBLIC);
    
    展开全文
  • PID控制器开发笔记之十二:模糊PID控制器的实现

    万次阅读 多人点赞 2018-11-10 19:14:06
    在现实控制中,被控系统并非是线性时不变的,往往需要动态调整PID的参数,而模糊控制正好能够满足这一需求,所以在接下来的这一节我们将讨论模糊PID控制器的相关问题。模糊PID控制器是将模糊算法与PID控制参数的自整...

    在现实控制中,被控系统并非是线性时不变的,往往需要动态调整PID的参数,而模糊控制正好能够满足这一需求,所以在接下来的这一节我们将讨论模糊PID控制器的相关问题。模糊PID控制器是将模糊算法与PID控制参数的自整定相结合的一种控制算法。可以说是模糊算法在PID参数整定上的应用。

    1、模糊算法的原理

    模糊算法是一种基于智能推理的算法,虽然称之为模糊算法其实并不模糊,实际上是一种逐步求精的思想。一个模糊控制器主要是由模糊化,模糊推理机和精确化三个功能模块和知识库(包括数据库和规则库)构成的。在此我们近讨论模糊控制的几个主要问题。

    1.1、输入量的量化

    输入数据都是精确的,要实现模糊算法需要现对其实现量化。所谓量化就是通过量化函数将输入量投射到一定的数字级别,一般都是相对于0对称的数字区间。具体投射到怎样的区间根据实际情况而定,因为这会直接影响到计算的精度。

    1.2、模糊化

    模糊化是模糊算法非常重要的一步,首先确定对应各语言变量的模糊子集,然后根据量化的结果,我们就可以判断该输入所属的集合并计算出对应的隶属度。计算隶属度的方法有很多,最常用的是使用三角形隶属度函数或梯形隶属度函数等来计算获得。

    1.3、规则库

    规则库是基于控制量的模糊化而的味道的,是实现模糊推理的基础,很大程度上依赖于经验来完成。规则库的表现形式可以有多种,具体实现的形式根据我们实现的方便。

    1.4、推理机

    推理决策才是模糊控制的核心,它利用知识库中的信息和模糊运算方式,模拟人的推理决策的思想方法,在一定的输入条件下激活相应的控制规则给出适当的模糊控制输出。

    1.5、精确化

    我们通过模糊推理,得到一系列的模糊表达,需要进行解模糊操作才能得到紧缺的数据。常用的解模糊方法有:

    • 最大隶属度法——计算简单,适用于控制要求不高场合。

    • 重心法——输出更平滑,但计算难度大

    • 加权平均法——一般在工业上应用最广泛

    1.6、工程量化

    系统控制输出是一个精确的数,但不是可以直接用于对象控制的物理量,所以在最后还要按照我们的需要进行转换。比如对应PID的参数则可进行必要的转换和修正在输出给PID控制器。

    2、模糊PID算法的设计

    前面简单的描述了模糊算法的基本原理,接下来我们将讨论如何将其应用于PID控制当中。所谓模糊PID控制是以偏差e及偏差的变化ec为输入,利用模糊控制规则在线对PID参数进行调整,以满足不同的偏差e和偏差的增量ec对PID参数的不同要求。其结构图如下:

    2.1输入值的模糊化

    输入值的模糊化就是将用于计算的输入对应到标准化的数值区间,并根据量化结果和模糊化子集得到该输入对子集的隶属度。我们在使用偏差e和偏差增量ec作为输入实现控制参数调整则需要对e和ec进行模糊化。

    首先,我们确定e和ec的模糊子集,对于PID控制我们选则:负大[NB]、负中[NM]、负小[NS]、零[ZO]、正小[PS]、正中[PM]、正大[PB]等7个语言变量就能够有足够精度表达其模糊子集。所以我们定义e和ec的模糊子集均为{NB,NM,NS,ZO,PS,PM,PB}。

    确定了模糊子集,我们怎么将e和ec的具体值和模糊集对应上呢?我们需要引入量化函数。要确定量化函数,我们先引入e和ec模糊集对应的论域,定义为{-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6}。对于任何一个物理量测量信号都有一个量程范围,我们记为Vmax和Vmin,和自然在PID调节时设定值的范围预期相同,所以偏差e的范围就是Vmin-Vmax到Vmax-Vmin的范围内,而偏差的增量范围则是其两倍。这里我们采用线性方式量化,则其函数关系为:

    利用上述的量化函数就可以将e和ec量化,我们可以采用如4舍5入的方式获取确定的模糊子集。但考虑到e和ec的变化是连续变化的,4舍5入对控制精度可能存在影响,所以我们引入隶属度来实现这一过程。

    最后我们确定e和ec在模糊子集上的隶属度。隶属度是一个介于0和1之间的值,用以描述对应一个输入属于某一个模糊自己的程度。一般我们描述成隶属度函数,可采用的隶属度函数很多,我们在次采用线性的隶属度函数,或者称为三角隶属度函数,其函数关系如下:

    如果我们量化后的结果是1,那么属于ZO的隶属度为0.5,同样属于PS的隶属度也是0.5。至此,模糊化全部完成。

    2.2、建立模糊规则表

    前面我们简述了输入的模糊化,但模糊推理才是模糊控制的根本。为了实现模糊推理首先我们要建立模糊推理的规则库或者称知识库,然后建立推理机进行推理。

    首先,我们来建立模糊规则库,在这里我们要对Kp、Ki和Kd三个参数进行调整,所以要建立这3个变量的模糊规则库。

    2.2.1、Kp模糊规则设计

    在PID控制器中,Kp值的选取决定于系统的响应速度。增大Kp能提高响应速度,减小稳态偏差;但是,Kp值过大会产生较大的超调,甚至使系统不稳定减小Kp可以减小超调,提高稳定性,但Kp过小会减慢响应速度,延长调节时间。因此,调节初期应适当取较大的Kp值以提高响应速度,而在调节中期,Kp则取较小值,以使系统具有较小的超调并保证一定的响应速度;而在调节过程后期再将Kp值调到较大值来减小静差,提高控制精度。基于上述描述我们定义Kp的模糊规则如下:

    2.2.2、Ki模糊规则设计

    在系统控制中,积分控制主要是用来消除系统的稳态偏差。由于某些原因(如饱和非线性等),积分过程有可能在调节过程的初期产生积分饱和,从而引起调节过程的较大超调。因此,在调节过程的初期,为防止积分饱和,其积分作用应当弱一些,甚至可以取零;而在调节中期,为了避免影响稳定性,其积分作用应该比较适中;最后在过程的后期,则应增强积分作用,以减小调节静差。依据以上分析,我们制定的Ki模糊规则如下:

    2.2.3、Kd模糊规则设计

    微分环节的调整主要是针对大惯性过程引入的,微分环节系数的作用在于改变系统的动态特性。系统的微分环节系数能反映信号变化的趋势,并能在偏差信号变化太大之前,在系统中引入一个有效的早期修正信号,从而加快响应速度,减少调整时间,消除振荡.最终改变系统的动态性能。因此,Kd值的选取对调节动态特性影响很大。Kd值过大,调节过程制动就会超前,致使调节时间过长;Kd值过小,调节过程制动就会落后,从而导致超调增加。根据实际过程经验,在调节初期,应加大微分作用,这样可得到较小甚至避免超调;而在中期,由于调节特性对Kd值的变化比较敏感,因此,Kd值应适当小一些并应保持固定不变;然后在调节后期,Kd值应减小,以减小被控过程的制动作用,进而补偿在调节过程初期由于Kd值较大所造成的调节过程的时间延长。依据以上分析,我们制定Kd的模糊规则如下:

    接下来,根据偏差E和偏差增量EC模糊化的结果以及规则库推理出∆Kp、∆Ki、∆Kd对应的模糊子集。由于前面我们设计的是采用隶属度函数来定义输入输出量在模糊子集的隶属度,所以推理出来的∆Kp、∆Ki、∆Kd的模糊子集通常是一个由模糊变量组成的矩阵。而输入量E和EC则是一个由模糊变量组成的向量。

    最后,我们需要明确不同的模糊变量所对应的量化数据。这个量化数据与物理量的对应则根据具体的不同对象是完全不一样的。

    2.3、解模糊处理

    对于求得的目标对象,我们还需要将其你模糊处理以使其与具体的物理量相对应。在模糊PID调解中,我们需要的是Kp,Ki和Kd,所以我们需要根据模糊推理的结果得到我们想要的Kp,Ki和Kd值。

    我们前面设计了三角隶属度函数,并采用相同的量化目标即论域{-6,6},所以在某一时刻,输入输出所处的模糊变量的隶属度是相同的,基于这一基础,我们采用重心法计算各输出量的量化值。其公式如下:

    其实因为我们采用的隶属度函数的特性,在任何方向的计算隶属度的和均为1,所以分母可以省略。于是每一个对象的计算实际上就是矩阵操作,公式如下:

    如果使用的是量化值,则还需要转为实际值,关于这一点直接使用物理量值也是没问题的,怎么处理根据实际需要确定。得到增量后,我们也可以引入系数来放大和缩小Kp,Ki和Kd变化量,具体实现公式如下:

    ,其中∆K为我们所计算得到的值,而α为系数,设定增量对最终只的影响。

    3、模糊PID算法实现

    前面我们描述了算法的全过程,接下来我们编码实现之。首先我们依然需要定义一个模糊PID控制器的结构对象。

    /*定义结构体和公用体*/
    typedef struct
    {
      float setpoint;               /*设定值*/
      float kp;                     /*比例系数*/
      float ki;                     /*积分系数*/
      float kd;                     /*微分系数*/
      float lasterror;              /*前一拍偏差*/
      float preerror;               /*前两拍偏差*/
      float deadband;               /*死区*/
      float output;                 /*输出值*/
      float result;                 /*物理量输出值*/
      float maximum;                /*输出值的上限*/
      float minimum;                /*输出值的下限*/
    
      float maxdKp;                 /*Kp增量的最大限值*/
      float mindKp;                 /*Kp增量的最小限值*/
      float qKp;                    /*Kp增量的影响系数*/
      float maxdKi;                 /*Ki增量的最大限值*/
      float mindKi;                 /*Ki增量的最小限值*/
      float qKi;                    /*Ki增量的影响系数*/
      float maxdKd;                 /*Kd增量的最大限值*/
      float mindKd;                 /*Kd增量的最小限值*/
      float qKd;                    /*Kd增量的影响系数*/
    }FUZZYPID;

    接下来,实现输入值的模糊化。我们前面已经设计了采用线性量化函数以及三角隶属度函数,所以实现就简单了。

    /*线性量化操作函数,论域{-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6}*/
    static void LinearQuantization(FUZZYPID *vPID,float pv,float *qValue)
    {
      float thisError;
      float deltaError;
    
      thisError=vPID->setpoint-pv;                  //计算偏差值
      deltaError=thisError-vPID->lasterror;         //计算偏差增量
    
      qValue[0]=6.0*thisError/(vPID->maximum-vPID->minimum);
      qValue[1]=3.0*deltaError/(vPID->maximum-vPID->minimum);
    }

    对于量化函数实际上可根据需要采用不同的函数,如速降曲线函数,正太分布函数以及其它一元函数等都是可以的,但对于我们在这里的实现目标使用线性函数就足够了。还有隶属度函数也是一样有多种选择,我们这里采用计算量较小的三角隶属度函数:

    /*隶属度计算函数*/
    static void CalcMembership(float *ms,float qv,int * index)
    {
      if((qv>=-NB)&&(qv<-NM))
      {
        index[0]=0;
        index[1]=1;
        ms[0]=-0.5*qv-2.0;  //y=-0.5x-2.0
        ms[1]=0.5*qv+3.0;   //y=0.5x+3.0
      }
      else if((qv>=-NM)&&(qv<-NS))
      {
        index[0]=1;
        index[1]=2;
        ms[0]=-0.5*qv-1.0;  //y=-0.5x-1.0
        ms[1]=0.5*qv+2.0;   //y=0.5x+2.0
      }
      else if((qv>=-NS)&&(qv<ZO))
      {
        index[0]=2;
        index[1]=3;
        ms[0]=-0.5*qv;      //y=-0.5x
        ms[1]=0.5*qv+1.0;   //y=0.5x+1.0
      }
      else if((qv>=ZO)&&(qv<PS))
      {
        index[0]=3;
        index[1]=4;
        ms[0]=-0.5*qv+1.0;  //y=-0.5x+1.0
        ms[1]=0.5*qv;       //y=0.5x
      }
      else if((qv>=PS)&&(qv<PM))
      {
        index[0]=4;
        index[1]=5;
        ms[0]=-0.5*qv+2.0;  //y=-0.5x+2.0
        ms[1]=0.5*qv-1.0;   //y=0.5x-1.0
      }
      else if((qv>=PM)&&(qv<=PB))
      {
        index[0]=5;
        index[1]=6;
        ms[0]=-0.5*qv+3.0;  //y=-0.5x+3.0
        ms[1]=0.5*qv-2.0;   //y=0.5x-2.0
      }
    }

    接下来,我们实现模糊推理的函数,有了前面的基础和模糊规则库,模糊计算的函数其实已经简单了。

    /*解模糊化操作,根据具体的量化函数和隶属度函数调整*/
    static void FuzzyComputation (FUZZYPID *vPID,float pv,float *deltaK)
    {
      float qValue[2]={0,0};        //偏差及其增量的量化值
      int indexE[2]={0,0};          //偏差隶属度索引
      float msE[2]={0,0};           //偏差隶属度
      int indexEC[2]={0,0};         //偏差增量隶属度索引
      float msEC[2]={0,0};          //偏差增量隶属度
      float qValueK[3];
    
      LinearQuantization(vPID,pv,qValue);
    
      CalcMembership(msE,qValue[0],indexE);
      CalcMembership(msEC,qValue[1],indexEC);
    
      qValueK[0]=msE[0]*(msEC[0]*ruleKp[indexE[0]][indexEC[0]]+msEC[1]*ruleKp[indexE[0]][indexEC[1]])
                +msE[1]*(msEC[0]*ruleKp[indexE[1]][indexEC[0]]+msEC[1]*ruleKp[indexE[1]][indexEC[1]]);
      qValueK[1]=msE[0]*(msEC[0]*ruleKi[indexE[0]][indexEC[0]]+msEC[1]*ruleKi[indexE[0]][indexEC[1]])
                +msE[1]*(msEC[0]*ruleKi[indexE[1]][indexEC[0]]+msEC[1]*ruleKi[indexE[1]][indexEC[1]]);
      qValueK[2]=msE[0]*(msEC[0]*ruleKd[indexE[0]][indexEC[0]]+msEC[1]*ruleKd[indexE[0]][indexEC[1]])
                +msE[1]*(msEC[0]*ruleKd[indexE[1]][indexEC[0]]+msEC[1]*ruleKd[indexE[1]][indexEC[1]]);
    
      deltaK[0]=LinearRealization(vPID->maxdKp,vPID->mindKp,qValueK[0]);
      deltaK[1]=LinearRealization(vPID->maxdKi,vPID->mindKi,qValueK[1]);
      deltaK[2]=LinearRealization(vPID->maxdKd,vPID->mindKd,qValueK[2]);
    }

    至此,Kp、Ki和Kd的增量已经得到,剩下的就是修正三个参数,并用于实现PID调节,与普通的增量型PID无异,不再赘述。

    4、总结

    模糊PID算法是模糊算法在PID参数整定上的应用,与纯粹的模糊控制算法是有区别的。普通的模糊控制器适用于直接推理控制器的输出,而模糊PID算法使用模糊算法修改PID参数,最终的控制器输出依然是由PID控制器来实现的。

    模糊控制本身是非常复杂且具体应用方式很多。大多是针对特定对象的专业控制器,已经脱离了PID这种通用性控制器的范畴。此外比较热门的还有模糊多变量控制器是属于先进控制系统(APC)的范畴,有机会再讨论。

    欢迎关注:

    展开全文
  • 工业机器人控制器

    万次阅读 多人点赞 2019-06-08 13:36:08
     机械臂控制器 移动机器人控制器  1. 机械臂控制器   机械臂类的控制器发展较早,相对成熟,先来看看现有的控制系统方案。 厂家 硬件 操作系统 ABB x86 VxWorks KUKA x86 V...

    编辑中未完成,先不要转载……

    工业机器人控制器调研

    初稿完成于 2019-6-8
    robinvista2@gmail.com
      

      如同大脑之于人一样,控制器也是机器人最重要的元部件,它定义了机器人的功能和行为。很多学者都对其进行了研究或给出了设计方案[1,2,3]^{[1,2,3]},但是针对控制器总体架构和具体实现的讨论较少,而且与工业生产一线严重脱节,早已过时。本文比较了机械臂和移动机器人两种工业机器人的控制器方案,对其功能需求和特点进行了分析,并探讨开放式控制器的实现方案。

     
      机械臂控制器                     移动机器人控制器
      以上分类的依据是机器人类型。目前市面上更多的控制器产品是通用型运动控制器或运动控制卡,即控制各种非标设备运动的,例如数控机床、激光切割机等自动化设备。当然这些产品也可以通过二次开发用于控制机器人。
    通用运动控制器产品

    1 软硬件方案

      我们首先考察常见工业机器人控制器的软硬件方案。

    1.1 机械臂

      机械臂控制器的发展较早,产品相对成熟,其实现方案见下表。国际一线品牌大多采用X86芯片,并采用实时操作系统构造底层软件。

    厂家 硬件 操作系统
    ABB x86 VxWorks
    KUKA x86 VxWorks+Windows(VxWin)
    KEBA x86 VxWorks
    B&R x86 Windows 10/B&R Linux 9
    固高 x86 Windows CE
    MUJIN x86
    纳博特 x86 VxWorks 或 Linux(PREEMPT_RT)或 SylixOS

    1.2 移动机器人

      移动机器人的控制器属于较新的方向,AGV、无人机、工程机械等都可归于此类,最近比较火的无人驾驶也可以认为是一种移动机器人,其控制系统底层方案见下表。

    厂家 硬件 操作系统 软件 外部接口
    Hesmor Infineon XC167 CoDeSys CAN
    Hirschmann PowerPC CoDeSys CAN
    EPEC Infineon C166 CoDeSys CAN
    NDC ARM Cortex-A8 Linux 内置陀螺仪、CAN、WLAN、485
    IFM Infineon TriCore 1796 CoDeSys CAN

    1.3 对比

      机械臂的功能要求多,自由度多,而且对运动精度和响应速度的要求较高,比移动机器人一般要高1到2个数量级,因此控制器的计算量大、周期短;移动机器人一般对响应速度要求不高,功能相对简单,其配置相对较低,而且移动机器人通常采用电池供电,控制器内置,因此对功耗和散热有要求,其控制器多采用嵌入式芯片。
      机械臂一般工作于固定的区域,其控制器通常放置于机箱内,因此防护等级不高,一般是IP20;移动机器人由于需要经常运动,尤其是室外工程机械,要考虑防水防尘,其防护等级较高,一般是IP65。

    机械臂 移动机器人
    控制精度 0.01~0.5mm 1~20mm
    控制周期 100us~10ms 10ms~100ms
    插补 需要 不需要
    轨迹规划 需要 不需要
    逻辑控制 需要 需要

    2 商业控制器

      介绍几种有代表性的商业控制器方案。

    2.1 CoDeSys

      很多机器人控制软件都是借助CoDeSys实现的,那么CoDeSys是什么呢?
      CoDeSys是德国3S公司推出的一款付费的软PLC开发软件,简单来说,它包括两部分:Development System和Runtime System。Development System就是用来编程的软件界面(就像Visual Studio、Eclipse等软件,也可以称为IDE),设计、调试、编译PLC程序都在IDE中进行,这部分是用户经常打交道的;程序写好了以后,就要把它转移到硬件设备中执行。可是这时生成的PLC程序自己是无法运行的,它还要在一定的软件环境中才能工作,这个环境就是Runtime System(也叫运行核),这部分是用户看不到的。二者安装的位置通常不同,IDE一般安装在用户的开发计算机上,Runtime System则位于起控制作用的硬件设备上,程序通过网线或串口线下载到Runtime中运行。

      CoDeSys在工业控制领域的应用非常广泛,上面提到的很多机器人公司都使用了它的产品,例如KEBA、倍福、固高、台达、广州启帆机器人、新时达机器人。3S公司只卖底层软件,不卖硬件和上层应用程序,应用程序和硬件电路需要由用户自己设计,3S公司负责将Runtime System移植到客户的硬件上。Runtime System可以裸跑在硬件上,但一般是运行在操作系统上,配置操作系统也是客户的工作。如果客户要求,CoDeSys的IDE可以定制,换成客户的logo和外观,这就是为什么你会发现不同厂家的开发平台长得不一样,但风格又比较相似。当然,用户也可以使用其它IDE,例如倍福就使用了Visual Studio,而背后的编译器等内核功能以及函数库仍然采用CoDeSys的方案。CoDeSys的Runtime具有强大的适应性,支持绝大多数的操作系统和芯片类型。

      CoDeSys的IDE部分是免费的,你可以从官网下载体验。真正收费的是运行系统Runtime System以及一系列的通信、运动控制组件。

      CoDeSys采用.Net技术开发,其在设计之初就将功能划分为若干组件模块,例如总线协议栈、可视化界面、运动控制、安全控制等等,用户可以像搭积木一样选购必需的模块搭建自己的系统,最后形成一个定制化的控制软件平台。一些初次接触软PLC的用户可能对这部分感到陌生,但其实这种设计方式非常普遍。举几个例子,MATLAB Simulink的实时工具箱(Real-Time)就是这样的工作方式,用户在Simulink的图形界面里通过拖拽设计控制程序,然后下载到真实的硬件中跑,可以在这里了解。还有像倍福也是这样的使用方式,用户在TwinCAT IDE里进行编程,然后下载到倍福的控制器中,控制器里面其实已经预装了一个Runtime。西门子的STEP7也是一款IDE,它的PLC中也存在一个配套的Runtime。只不过西门子(包括日系PLC)的系统封闭而保密,外人不知道他的系统架构。
      用户编写的PLC程序就像我们电脑里的应用程序,它运行在Runtime System上,而Runtime System又运行在操作系统之上。由于Runtime System位于应用程序和操作系统中间,所以又被称为中间件(Middleware)。简单来说,你可以把中间件看成是由驱动程序、基本的函数库等等模块组成的软件系统。因为这些程序模块主要与硬件或者底层软件打交道,与用户关系不大,所以被组织成了单独的一块。这些软件呈现给用户的是函数调用接口,也就是说你只需要会使用就行了,不用操心具体怎么实现,因为这些是驱动工程师和算法工程师的活儿。当然,大多数时候你也看不到这部分的具体实现,因为它们是以编译后的二进制文件的形式提供给你的,根本无法阅读,你顶多能看到一些头文件,其中只是一些函数和变量定义,没有什么干货。在机器人软件里面,处于同样地位的还有ROS、OROCOS等。
      机器人的控制,像数控机床一样,对实时性有要求,因此我们选择的操作系统最好是实时操作系统(RTOS)。遗憾的是,我们经常用的操作系统都不是实时的,例如Windows和Linux。实时操作系统有两种实现方式:
      1. 放弃通用的操作系统,从底层重新开始设计,代表性的有VxWorks、QNX、WinCE、μC/OS、LynxOS等;这种方式的缺点是所有的任务都是实时的,即使任务本身没有实时的必要,例如网络访问、文件系统访问,因此你得专门开发适用于这种操作系统的应用程序,工作量可能比较大。VxWorks在军事和工业应用较多,例如被应用于战斗机和火箭上。VxWorks留下了一个空白,这就是车载领域,现在这个市场被QNX占据了。
      2. 通过对通用的操作系统打补丁(添加扩展),使其具备实时性,代表性的有Windows RTX、Xenomai、RT Linux、RTAI,这种方式的缺点是,对实时任务的支持(资源)没有第一种方式多;
      考虑到Windows和Linux这两款操作系统的用户较多,CoDeSys推出了相应的实时补丁(RTE),为用户免去了改造的烦恼。想了解更多的CoDeSys Runtime信息可以阅读官方的文档[1][2][1][2]
      CoDeSys runtime如果不安装在操作系统之上,则需要其自己备有简单的调度程序。CoDeSys自带的调度程序比较简单,有两种[5]^{[5]}
      1 Embedded Scheduler 这种是简单的轮询,一个任务结束前另一个任务不能运行,任务之间不能抢占,实际上这种方式并不是实时的;
      2 Timer Scheduler 为每个任务分配一个定时器,定时触发;
      CoDeSys给机器人厂家开发控制器带来了便利,但是依靠CoDeSys这类商业软件打造自己的控制器产品也存在不少的缺点:
      1 底层算法不公开
      CoDeSys集成的运动控制组件、总线协议栈都是封装好的,用户无法了解其内部细节,也无法针对自己的具体需求进行定制优化,只能简单地调用。用户只能依附于CoDeSys平台,难以形成自己的技术。
      2 功能有限,难以扩展
      现在以机器视觉、人工智能、自动驾驶等为代表的新技术突飞猛进,而工业控制上的很多技术仍然停留在20年前。以移动机器人中的导航场景为例,基于视觉或者激光的导航方法需要采集大量的数据并对其进行处理,其中涉及相当多的矩阵计算。而现在PLC只能进行落后的一维数字计算,难以实现复杂的算法。与人工智能圈子喜欢开源的风格正好相反,工业控制圈子相互封闭,谁都不肯开放自家的函数库,开源函数库很少,就连最基本的滤波算法、矩阵计算都要自己从头开始写。而且,国际标准IEC提供的标准函数太过有限,完全无法适应新的场景,急需扩展。
      3 成本高、难以更新
      商业软PLC成本动不动几十万,这还不包括各种总线通信库、运动控制库、可视化库,这些仍需单独购买,而且需要从售出产品上提成,对于小团队来说成本难以接受。由于完全依赖CoDeSys,客户自己产品硬件的升级换代需要重新定制移植,导致成本增加。这让笔者想起来曾经微软给手机打造的操作系统Windows Phone,微软在移动端是如何一步步作死的呢?其中关键的一条就是向手机厂商收取高额的授权费,可能微软当大爷当惯了,而且更不要脸的是给用户设置障碍,同一款手机系统不能连续升级。

      GEB Automation也推出了与CoDeSys类似的软PLC,支持编程、调试、仿真,面向OEM的产品售价9500美元,比CoDeSys好的是一次性付费不再收取单机提成,可以移植到常用的硬件平台,其IDE基于Eclipse开发。

    2.2 菲尼克斯PLCnext

      2019年菲尼克斯高调推出了新一代PLC,被称为PLCnext技术。PLCnext采用通用的软硬件,例如ARM处理器和RTLinux操作系统,因此其也可视为一个软PLC安装于标准硬件平台之上,而PLCnext在中间层仍然采用了KW的软运行核。PLCnext支持C/C++、IEC 61131-3标准PLC语言、Matlab等编程语言,为不同用户开发项目提供了便利。PLCnext底层是一个实时操作系统RTLinux,其上允许客户运行自己的非实时应用程序,并且提供非实时应用程序于PLC实时程序的数据访问接口。开放式PLC是未来的潮流,可以看到PLCnext符合这一趋势,反之如果你用西门子的PLC,想做一点扩展是连门都没有滴。

      菲尼克斯PLCnext的核心技术体现在两个方面:任务执行管理器(ESM)和全局数据管理器(GDS)。菲尼克斯为ESM和GDS申请了专利。
      任务执行管理器确保不同优先级的任务按照正确的优先级和时序运行,并保证低优先级的任务被抢占时数据的一致性。下图是一个简单的例子,其中有两个任务(上面一行是任务1,下面一行是任务2),任务1每5ms运行一次,它的优先级比任务2高,所以在任务2运行过程中会被任务1抢占。

      全局数据管理器负责任务间的通信,也就是交互数据。除了任务之间,每个任务内部可能有不同语言编写的函数模块,它们之间也需要交互数据。全局数据管理保证所有的数据在交换过程中的一致性。同样是上面的例子,任务2从被抢占恢复后,数据应该与被抢占前是一样的(即绿色箭头所示的变量5和8),如果不一样就会出现所谓的“数据不一致”现象,对于实时系统这一般是不允许的。全局数据管理器的作用就是负责数据交换的一致性。

    2.3 KEBA

      KEBA是一家奥地利机器人控制器制造商,其编程和控制软件全部建立在CoDeSys软PLC之上,CoDeSys为KEBA提供了基本的编辑、编译、调试等功能。CoDeSys本身与机器人相关的功能很少,因此机器人涉及的功能和函数是由KEBA开发的,以库的形式在CoDeSys中调用。为了保证实时性,控制器里的CoDeSys Runtime安装在了VxWorks之上。

    2.4 KUKA

      KUKA的新一代控制器称为KR C4,其同样采用了软PLC的方案。该方案由KW公司提供[4]^{[4]},软PLC由IDE部分(被称为Multiprog)和Runtime(被称为ProConOS)组成。ProConOS由C#开发。ProConOS Runtime同样运行在VxWorks之上,它们安装在控制器硬件中,其硬件采用了Intel双核CPU。

      

    2.5 欧姆龙

      欧姆龙(OMRON)推出了“机器人集成控制器”——NJ501-R,将PLC,运动和机器人控制集成在单个控制器中。PLC和机器人的编程语言统一在通用的IEC语言中,这使通常管理PLC的工程师也可以管理机器人。PLC与NC程序在同一个机器上执行,能让多个任务同步。

    2.6 百度自动驾驶计算平台

      百度的Apollo无人车项目推出了无人车自动驾驶专用计算平台——ACU (Apollo Computing Unit)。在网络直播《百度ACU软硬件结合优化的实践经验分享》中介绍了ACU的原理和实现。ACU采用了赛灵思的ZU5芯片,这是一个异构多核SoC处理器,上面集成了CPU(ARM V8核)、FPGA、DDR内存(2GB)、还有一个很小的GPU。

      研发工程师认为算力并不与帧率严格成正比,例如常用芯片的算力是TFLOPS级别的,而内存带宽是GFLOPS级别的,也就是说算力是内存读取速度的1000倍,此时单纯增加算力已经不能提高计算速度,因为内存是这时的瓶颈。   为什么采用这种芯片是和自动驾驶中执行的具体计算任务有关的。自动驾驶中包含多种计算任务,其中最主要的就是人工智能算法,也就是深度学习。深度学习需要的计算量是其它任务的10倍以上,所以必须有强大的计算硬件支持。FPGA是算力最强大的可以执行计算密集型任务,非常适合深度学习这样的任务。虽然深度学习的计算量占总体任务的绝大多数,但是自动驾驶中还有大量的其它任务,例如图像处理、SLAM,它们的计算量不大但是计算时间并不可忽略,这时需要由CPU完成。百度针对深度学习的底层计算进行了很多优化,例如采用8bit INT型数据类型减少计算量(同时不降低准确度),把常用的“多个算子组合”融合成一个,用Average pooling替代Max pooling,采用共享内存实现零拷贝。

    3 开源控制软件

      目前存在一些开源的控制系统方案,例如ROS、Orocos、OpenRTM、Beremiz、OpenPLC、XBotCore、ArmarX、ORCA、AMiRo-OS。
      PLCopen定义了伺服和运动控制的一些标准,包括编程语言、运动控制基础函数块(Function Block)、输入输出接口的参数等[3]^{[3]},但是并没有给出具体的实现代码细节,这个是由各个厂家提供的。

    3.1 ROS

      ROS的前身最早可以追溯到2007年斯坦福大学的博士生Eric Berger和Keenan Wyrobek的工作,主要开发语言是C++。虽然ROS的名字听起来是一个机器人操作系统,但其实它不是。ROS是一个中间件,它安装在真正的计算机操作系统之上。刚开始,ROS有点像一个大杂烩,包括一些通信用的组件、可视化和仿真组件、坐标系管理组件。很多人将ROS描述为软件框架,但笔者尽量避免使用这些抽象而又吓人的名词,因为大多数人并不熟悉机器人软件系统,它容易让本来就稀里糊涂的读者更摸不着头脑。
      ROS提供的功能有:
      1 节点定义和节点间的通信方式:节点是一个应用程序模板,用户将自己的算法代码添加进去,剩下的交给ROS
      2 基本工具:机器人常用的函数库(运动规划、SLAM、逆运动学)、可视化工具、数据记录等机器人开发常用的功能
      3 设备驱动:用户拿到硬件不再需要从零开发,节省时间
      ROS在工业界用的并不多,这一点也不奇怪,因为它在设计之初考虑更多的是通用性和代码重用能力,不太关心可靠性、实时性等。最开始百度公司在其无人驾驶车辆上使用了ROS作为平台,当时的考虑可能是快速完成无人驾驶算法的验证。随后,意识到ROS自身的一些问题,百度无人车团队尝试对其进行改造。但是,他们最终放弃了转而选择重新搭建一套软件——Apollo Cyber RT。
      ROS变得像今天这么火完全出乎设计者的意料,他们并没想到ROS会被用在各种各样的机器人上。中国也有一些人计划设计自己的机器人软件系统,例如上海交通大学中国科学院的micROS。

    3.2 Orocos

      Orocos是一个开源的机器人控制程序开发软件,由比利时鲁汶大学的Herman Bruyninckx及其博士生Peter Soetens开发,编程语言为C++。 Orocos的介绍文档偏软件开发,非程序员不容易读懂。
      Orocos的地位与ROS有些类似,但定位于控制,其位于实时操作系统之上,提供的基本功能包括:生成实时控制程序的工具链(编译器),组件模板、机器人常用基本函数。Orocos替用户解决了模块功能和接口定义、模块间实时通信这些基本功能,借助这些软件模块,用户可以更快速的开发部署自己的应用软件。Orocos既关注上层应用层,也关注底层控制层。与ROS相比,Orocos在设计之初就考虑了实时性。在Peter Soetens的博士论文[4]^{[4]}里,对于实时性的讨论占了很大篇幅。Orocos直接使用了底层操作系统(例如Xenomai)的任务调度模块,因此Orocos必须安装在实时操作系统上才能保证实时性。

    3.3 Beremiz

      Beremiz是一个免费、开源的软PLC控制系统,由法国人Edouard Tisserant开发[4]^{[4]},主要开发语言是Python。出于对传统PLC壁垒森严的不满,Tisserant倡导了开源项目Beremiz,他也是CANfestival的作者。

      Beremiz项目始于2005年,雏形只是一个编辑器,随后其它功能逐渐加入从而形成了一个完整的软PLC开发环境,其功能特点如下:
      1 支持多任务,多任务可配置不同的优先级,任务运行方式可以是周期式或中断触发式
      2 支持ST、梯形图等五种标准PLC编程语言
      3 提供IEC 61131-3标准规定的基本函数(定时器、比较、数学运算、类型转换、位操作、字符串等上百个函数)
      4 可扩展Modbus、CANopen、EtherCAT总线通讯模块(需自己移植到所选平台)
      5 支持C和Python语言,用户可以在PLC中调用C程序或者调用Python程序,也可以在Python中调用C程序
      6 支持仿真,但是不支持在线调试
      7 具有可视化界面(HMI),变量值可直观显示为图表
      Beremiz的工作方式为:用户使用PLC语言编写应用程序,不管用户采用ST语言还是梯形图或者其它PLC语言,Beremiz都将其翻译成C语言,这是由MatIEC组件完成的。随后,gcc编译器将生成的C语言程序与总线通信程序一起编译链接得到二进制目标文件(Linux下是so文件,Windows下则是dll文件)。再之后,二进制目标文件被下载到目标设备上,目标设备上预先安装了runtime,runtime对目标文件进行调用完成相应的控制功能[6,7,8,9]^{[6,7,8,9]}

      Beremiz的IDE和runtime两个部分的开发语言都是Python。只要可以运行Python的操作系都可以运行Beremiz,即其可在Windows、Linux、Mac OS等多种操作系统上运行,当然前提必须得有操作系统。Beremiz的任务调度完全依赖于操作系统,这意味着它的实时性受到操作系统的影响很大,因此最好选择实时操作系统,例如Xenomai、WinCE。
      Beremiz衍生出了一些软件控制方案,例如OpenPLC、KOSMOS,在这些衍生物里更多的功能插件被加了进来,例如运动控制函数、总线通信函数、配置插件。
      选择Python进行开发是因为这种语言简单易用,但是Python在工业控制领域很少使用,因为它无法提供实时性(受内存分配等因素影响)。即便如此,[10]{[10]}对Beremiz runtime的实时性进行了分析,并与CoDeSys runtime做了对比,结果表明Beremiz的实时性反而还优于CoDeSys。这可能是由于核心程序被翻译成C代码的原因,Python编写的runtime只是负责调用。这篇文章比较了C和用Python调用C的性能,性能差距并不是特别悬殊。
      Beremiz的介绍资料很少,并且其中一部分还是由俄文和法文撰写的,缺少深入探讨内部原理的文献。

    3.4 OpenPLC

      OpenPLC是一个免费开源的软PLC软件系统,它由Beremiz项目衍生而来,由美国阿拉巴马大学博士生Thiago Rodrigues Alves开发[13]^{[13]}

    3.5 对比

      大多数软件将任务的调度交给操作系统,这就带来一个问题:对于通用的操作系统的来说,每个进程基本是相互独立的,而对于机器人应用,任务间通常是相互依赖的,这就造成了操作系统的调度程序无法用于任务有依赖的任务调度。

    4 控制器的开发

      机器人控制器开发涉及的专业众多,需要一个团队完成。精通控制算法的机器人专业的博士对于软件开发可能也一窍不通,看到进程、任务调度、mutex这些计算机名词头大;训练有素的软件工程师对于齐次变换矩阵、旋量这些概念则是一头雾水;除此以外,项目还需要驱动工程师、硬件工程师,还要有工程师懂总线通信、熟悉工艺。如果想找业务能力扎实的员工,就要承担高昂的成本,没有诱惑力的工资是很难留住这些专业人士的。更何况中国的机器人教育其实还是相当落后的,能找到专业能力扎实的员工并不容易。笔者撰写本文的初衷也是为了向各方普及基础知识,铲平知识不对称的大山。
      由于开发机器人控制器成本高而且困难,大部分的厂家会选择在别人的基础上开发。

    4.1 控制器方案的选择

      单处理器还是多处理器?
      早期CPU的计算能力较弱,为了提高运行速度,不得不采用多CPU方案,一些计算量大的任务被剥离出来独占一个CPU。比较有代表性的就是各种控制板卡的方案,例如PMAC、固高。固高的GUC-ECAT控制器单独设计了一个DSP和一个FPGA来执行插补、轨迹规划等任务,另一个CPU一般执行非实时的人机交互,编程开发等任务。如果你拆开固高的机器人控制器,就会发现它有两个计算核心(Intel CPU和 DSP/FPGA),就像游戏电脑会有独立的显卡一样。当然,多一个核总没有坏处,比如NI的机器人控制器roboRIO除了有ARM核还带了一个FPGA,可以想象它的数据采集会比较快。也难怪它被用在了对控制周期和采样速率要求较高的场合,例如MIT的四足机器人(用的是cRIO-9082)。

      随着CPU核心数量增加和计算能力的提升,单CPU的性能越来越强,因此机器人控制器只使用一个CPU就够了,所有的实时和非实时任务都运行在这一个CPU上,由操作系统进行调度。
      操作系统还是裸跑?
      一般认为操作系统会导致额外的开销,毕竟上下文切换需要时间,但是半导体技术和软件技术的进步已经使这个差别非常小了。程序裸跑在硬件上适合比较简单、逻辑不复杂的应用场合,但是其缺点也是显而易见的,如果升级或者改变硬件平台,程序就要重写。所以现在的机器人(尤其是机械臂、无人驾驶汽车)控制器无一例外都使用了操作系统。
      半成品软件还是软PLC?
      ROS和OROCOS是半成品,它们更适合学术研究,需要用户对整个系统比较熟悉才能使用,对用户的编程能力有较高的要求,一般用在产品还没有定型的阶段或者用户不需要经常变换应用任务的场合。例如无人驾驶可以使用,因为无人驾驶的整个业务逻辑和任务基本不会有大的变动。正如手机或者汽车行业,厂家不会把电路板或者底盘直接卖给客户,因为客户不会使用。面向终端客户的产品必须要考虑产品本身的易用性和客户的能力。所以如果你的产品面向的是没有研发能力的终端客户,必须要有规范易用的编程界面和简洁高效的编程语言,这是ROS或OROCOS这种软件所不具备的。
      而软PLC自带IDE,用户可以直接在IDE中直观地编写自己的应用程序。如果自带的函数不够用,用户再去底层实现自己的函数。开发效率更高,使用更友好。因此,现在的机器人控制器都会采用软PLC的实现方式。
      笔者研究生毕业最早接触的机器人控制器不管看起来还是用起来都像个PLC,这让我很恼火。因为PLC是低级的玩意,它的编程语言居然是梯形图这种看起来像小学生比赛一样的东西,而且除了一些基本的函数,其它的什么都没有,做个矩阵计算什么的想都别想。
      是的,PLC编程简单而且皮实耐用,这是它设计的目的,但是机器人正在变得越来越不简单,更多的功能被加入进来,机器视觉、自主导航、运动规划、多轴运动控制,这些要求控制器提供更强大的支撑,而不仅仅是低端的逻辑控制或者简单的数值计算。所以,对于机器人控制来说,传统的硬PLC应该被淘汰了。
      我们需要的控制器软件应该足够开放,允许用户随时调整程序结构、加入新的功能,同时它自身应该提供足够的底层基础函数,例如线性代数、数学优化、插值拟合、方程求解、甚至图像处理、运动控制。在使用方式上,为了兼顾客户(不能要求所有客户都能自己开发高级功能),它还是尽量简单好,最好与PLC的使用差别不大。

    4.2 实时性

      开发机器人控制器是个繁重的工作,要明确一系列性能要求,首先就是实时性。
      如果问PLC或者机器人控制器与普通计算机的本质区别是什么,你会如何回答?是PLC更稳定吗,还是它的抗干扰能力更强、又或者是接口更丰富、或是编程语言更符合工业控制。笔者认为这些都不是,真正本质的区别在于PLC是实时的,而普通计算机不是实时的。家用电脑的信息处理能力可以轻松甩出PLC几条街(想想你玩大型游戏或者看高清视频的计算量),那么为什么工业上还是使用“落后的”PLC呢?答案就是实时性,实时性对于工业机器人来说是必须的(至于服务机器人笔者认为可以不强求)。一般人很容易错把“实时性”理解为计算速度快或者响应延时短,但其实“实时性”表示时间上的“确定性”,例如实时操作系统(RTOS)中的中断响应或者进程切换的延迟时间一定是在一个时间范围内,我们常用的操作系统(Windows、Linux)都不是实时操作系统,因为它们设计的出发点是大吞吐量,不能保证每个事件都在一定范围内得到处理。再比如,标准以太网的传输速度比实时工业以太网(比如EtherCAT)快多了,但是标准以太网却不是实时的,因为它同样不能保证数据在确定的时间内完成传输。
      以上都是定性的描述,能不能定量说明呢?当然了,确定性肯定是有具体指标的,脱离具体数字分析实时性没有意义。如果我们将反应时间规定为1个小时,那么就连Windows这样的操作系统也是实时的了,因为它响应再慢也不会花一个小时。工业上很多场合1个小时显然是太夸张了,我们至少要缩小到10ms这样的量级,例如一个控制或插补周期执行时间不能超过1ms,这样Windows系统肯定满足不了要求。最近炒的比较火的5G通信技术可以将延时控制在1ms左右,虽然它也不是实时的,但是由于速度足够快所以也可以用于工业控制领域取代有线通信,这就是为什么5G这么火的原因。
      理解实时性不太难,但是影响实时性的因素有哪些呢?这方面讨论涉及操作系统原理,各大机器人厂家肯定不会公开自己的测试和试验结果。评价实时性的主要指标是latency和jitter,jitter受到操作系统调度算法的影响很大,其它的例如系统负载也有影响,调度算法的影响大概是十微妙级的。jitter对机器人性能的影响不容易量化,因为中间环节有些复杂(底层伺服闭环)。
      影响实时性的另一个主要因素是内存分配。动态内存的分配耗时非常不确定,这也是为什么很多实时系统都避免采用动态内存。这里我举两个例子:
      1. 在PLC中不提供动态数组,只能用定长数组,也就是说使用之前必须先分配好数组长度。这显然很不方便,例如我们有时在函数调用时传递一个数组,而事先并不想考虑数组的大小。这样一来,我们只好计算好每次传递的数组长度,或者设置一个尽量大的数组,显然这会造成空间的浪费。

      2. 如果你有过在MATLAB Simulink中编写S函数或者用户自定义函数的经历,你就会发现,S函数中要求你在使用变量之前必须先进行定义或分配空间,不能像在m文件中一样不事先定义就赋值(可以看这个MATLAB自带的例子:Integrate MATLAB Algorithm in Model)。因为Simulink中的模块是可以生成C语言并导出到硬件上直接运行的,这意味着它对实时性有要求。一些PLC,例如前面提到的菲尼克斯和倍福,都支持将Simulink中仿真好的控制模型直接生成为控制程序,而无需重新编程。难怪我们在Simulink中编写S函数的时候总感觉不像在MATLAB写程序那么自由随意。

    4.3 高精度定时器

      我们经常提到“实时”,实时需要高精度的时间标准,那么谁来提供这个高精度的时间呢?答案就是时钟周期,它是是实时操作系统的心跳(或者脉搏)。周期性采集数据、任务定时切换、延时输出,这些功能都要求实时操作系统必须要有一个稳定的时钟周期来作为整个系统的时间标准。
      什么是时钟周期呢?时钟周期依赖一个定时器,它是个函数,其本质是一个计数器。定时器开始预先存储一个值,每次硬件(例如晶振)产生一个脉冲,就将这个值减一,减到0时再重置为初始值,同时产生一个中断,这个特定的周期性的中断称为“时钟周期”(Tick,有的也叫“时钟节拍”、“心跳”或“滴答”)。举个例子,假如晶振的频率是72MHz,则时钟周期(Clock Period)就是1/72M,如果预先存储的值是72000,那么时钟节拍就是1/72M ×\times 72000= 0.001s,也就说1ms产生一个中断,此时控制器无法分辨低于1ms的时间间隔。

    5 参考资料
        
    [1] 机器人控制器的现状及展望,范永,谭民,机器人,1999.
    [2] 开放式机器人控制器综述,孙斌,杨汝请,机器人,2001.
    [3] Robotics Middleware: A Comprehensive Literature Survey and Attribute-Based Bibliography,Ayssam Elkady,Journal of Robotics,2012.
    https://zhuanlan.zhihu.com/p/28052497
    [4] CODESYS Control V3 Manual, Document Version 19.0.
    [5] CODESYS Control V3 Migration and Adaptation, Document Version 4.0.
    [6] Robots Count on Software,KW-Software.
    [6] https://www.plcopen.org/technical-activities/motion-control
    [7] A Software Framework for Real-Time and Distributed Robot and Machine Control,Peter Soetens,Ph.D. thesis,2016.
    [8] An Open Source IEC 61131-3 Integrated Development Environment,Edouard Tisserant,IEEE,2007.
    [9] OPC UA support for Beremiz softPLC,Martim Afonso,2018.
    [10] An Open-source Development Environment for Industrial Automation with EtherCAT and PLCopen Motion Control,I. Kim,IEEE ETFA,2013.
    [11] Conception and Implementation of a Secure Engineering and Key Exchange Mechanism for the Open Source PLC Beremiz using a Test Driven Approach,M A Rahman,2016.
    [12] Can We Use Beremiz Real-time Engine for Robot Programmable Logic Controller,S Chu,CACS,2015.
    [13] OpenPLC - A fully open source controller An open source platform for PLC research,https://motion.control.com/thread/1464718978
    [14] OpenPLC: An Open Source Alternative to Automation,Thiago Rodrigues Alves,IEEE Global Humanitarian Technology Conference,2014.
    [15] 工业机器人控制器开放性、实时性分析方法以及单处理器模式下的实现,博士学位论文,谈世哲,2002.
    [16] Bare-Metal, RTOS, or Linux? Optimize Real-Time Performance with Altera SoCs,Chee Nouk Phoon,2014.
    [17] Real-time Operating System Timing Jitter and its Impact on Motor Control,F. M. Proctor,SPIE,2001.

    展开全文
  • java web 前端控制器 应用控制器 页面控制器 分别指的是什么啊?有什么作用? 麻烦大神详细一点谢谢
  • Thinkphp 控制器/控制器定义

    千次阅读 2018-09-14 14:16:53
    控制器定义 控制器和操作 一般来说,ThinkPHP的控制器是一个类,而操作则是控制器类的一个公共方法。 下面就是一个典型的控制器类的定义: &lt;?php namespace Home\Controller; use Think\Controller; ...

    控制器定义

    控制器和操作

    一般来说,ThinkPHP的控制器是一个类,而操作则是控制器类的一个公共方法

    下面就是一个典型的控制器类的定义:

    <?php
    namespace Home\Controller;
    use Think\Controller;
    class IndexController extends Controller {
        public function hello(){
            echo 'hello,thinkphp!';
        }
    }
    

    Home\IndexController类就代表了Home模块下的Index控制器,而hello操作就是Home\IndexController类的hello(公共)方法。

     

    当访问 http://serverName/index.php/Home/Index/hello 后会输出:

    hello,thinkphp!
    

    注意:如果你设置了操作方法绑定到类,则操作方法对应了一个类(参考操作绑定到类)。

     

    定义控制器

    控制器通常需要继承系统的Controller类或者其子类,例如,下面定义了一个 \Home\Controller\IndexController 控制器类:

    <?php
    namespace Home\Controller;
    use Think\Controller;
    class IndexController extends Controller {
        public function hello(){
            echo 'hello';
        }
    
        public function test(){
            echo 'test';
        }
    }
    

    控制器的名称采用驼峰法命名(首字母大写),控制器文件位于 Home/Controller/IndexController.class.php

    IndexController控制器类的hello和test方法就是操作方法,访问下面的URL地址:

    http://serverName/Home/Index/hello
    http://serverName/Home/Index/test
    

    会分别输出:

    hello
    // 和
    test
    

    操作方法的定义必须是公共方法,否则会报操作错误,所以,下面的操作定义只能访问hello操作,而不能访问test操作。

    <?php
    namespace Home\Controller;
    use Think\Controller;
    class IndexController extends Controller {
        public function hello(){
            echo 'hello';
        }
    
        protected function test(){
            echo 'test';
        }
    }
    

    注意:定义控制器方法的时候,尽量避免和系统的保留方法相冲突(除非你非常明确自己在做什么),这些保留方法名包括但不限于:

    display
    get
    show
    fetch
    theme
    assign
    error
    success
    

    因为操作方法就是控制器的一个方法,所以遇到有和系统的关键字冲突的方法可能就不能定义了,这个时候我们可以设置操作方法的后缀来解决,例如:

    'ACTION_SUFFIX'         =>  'Action', // 操作方法后缀
    

    设置操作方法的后缀为Action,这样,控制器的操作方法定义调整为:

    <?php
    namespace Home\Controller;
    use Think\Controller;
    class IndexController extends Controller {
        public function listAction(){
            echo 'list';
        }
    
        public function helloAction(){
            echo 'hello';
        }
    
        public function testAction(){
            echo 'test';
        }
    }
    

    操作方法的后缀设置只是影响控制器类的定义,对URL访问没有影响。

     

    多层控制器

    ThinkPHP的控制器支持多层和多级,多层指的是控制器可以分层,例如除了默认的Controller控制器层(我们可以称之为访问控制器),还可以添加事件控制器(层),例如:

    ├─Controller 访问控制器
    │  ├─UserController.class.php 
    │  ├─BlogController.class.php
    │  ...
    ├─Event 事件控制器
    │  ├─UserEvent.class.php  
    │  ├─BlogEvent.class.php
    │  ...
    

    访问控制器的名称是通过DEFAULT_C_LAYER设置的,默认是Controller。

    访问控制器负责外部交互响应,通过URL请求响应,例如 http://serverName/Home/User/index,而事件控制器负责内部的事件响应,并且只能在内部调用,所以是和外部隔离的。

    多层控制器的划分可以根据项目的需要自由分层。

     

    如果是定义其他的控制器层,则不一定必须要继承系统的Controller类或其子类,通常需要输出模版的时候才需要继承Controller类。例如:

    <?php
    namespace Home\Event;
    class UserEvent {
        public function login(){
            echo 'login event';
        }
    
        public function logout(){
            echo 'logout event';
        }
    }
    

    UserEvent事件控制器位于 Home/Event/UserEvent.class.php

    多级控制器

    多级控制器是指控制器可以通过子目录把某个控制器层分组存放,首先需要设置控制器的分级层次,例如,我们设置2级目录的控制器层:

    'CONTROLLER_LEVEL'      =>  2,
    

    控制器文件的位置放置如下:

    ├─Controller 访问控制器
    │  ├─User User分级(组)
    │  │  ├─UserTypeController.class.php 
    │  │  ├─UserAuthController.class.php 
    │  ...
    │  ├─Admin Admin分级(组)
    │  │  ├─UserController.class.php 
    │  │  ├─ConfigController.class.php 
    │  ...
    

     

    多级控制器中的命名空间需要这样定义:

    <?php
    namespace Home\Controller\Admin;
    use Think\Controller;
    class IndexController extends Controller {
        public function hello(){
            echo 'hello';
        }
    
        public function test(){
            echo 'test';
        }
    }
    

    然后就可以通过URL地址访问:

    http://serverName/Home/User/UserType
    http://serverName/Home/Admin/User
    

    如果希望简化URL地址中的模块地址,可以参考 模块部署

     

    实例化控制器

    访问控制器的实例化通常是自动完成的,系统会根据URL地址解析出访问的控制器名称自动实例化,并且调用相关的操作方法。

    如果你需要跨控制器调用的话,则可以单独实例化:

    // 实例化Home模块的User控制器
    $User = new \Home\Controller\UserController();
    // 实例化Admin模块的Blog控制器
    $Blog = new \Admin\Controller\BlogController();
    

    系统为上面的控制器实例化提供了一个快捷调用方法A,上面的代码可以简化为:

    // 假设当前模块是Home模块
    $User = A('User'); 
    $Blog = A('Admin/Blog');
    

     

    默认情况下,A方法实例化的是默认控制器层(Controller),如果你要实例化其他的分层控制器的话,可以使用:

    // 假设当前模块是Home模块
    // 实例化Event控制器
    $User = A('User','Event'); 
    $Blog = A('Admin/Blog','Event');
    

    上面的代码等效于:

    // 实例化Home模块的User事件控制器
    $User = new \Home\Event\UserEvent();
    // 实例化Admin模块的Blog事件控制器
    $Blog = new \Admin\Event\BlogEvent();
    
    展开全文
  • 一、控制器的结构和功能 运算器是组合逻辑电路(输入),控制器是时序逻辑电路(输入+状态) 控制器是计算机系统的指挥中心,控制器的主要功能有: 1)从主存中取出一条指令,并指出下一条指令在主存中的位置。 2)...
  • AngularJS控制器controller之间如何通信 angular控制器通信的方式有三种: 1,利用作用域继承的方式。即子控制器继承父控制器中的内容 2,基于事件的方式。即$on,$emit,$boardcast这三种方式 3,服务方式。写一个...
  • USB xHCI控制器使用总结

    万次阅读 2020-03-21 09:40:51
    USB xHCI控制器使用总结
  • RestFul和控制器

    千次阅读 2021-01-24 16:43:24
    控制器Controller 控制器复杂提供访问应用程序的行为,通常通过接口定义或注解定义两种方法实现。 控制器负责解析用户的请求并将其转换为一个模型。 在Spring MVC中一个控制器类可以包含多个方法 在Spring ...
  • MATLAB仿真PID控制器与模糊控制器

    千次阅读 多人点赞 2019-03-04 16:06:10
    摘要:使用matlab编写PID控制器与模糊控制器,并对原理进行解析。 背景: 小白自学。 基础:1、视频“自动控制原理”,1-3章,柠檬大学,点此链接 2、《基于MATLAB的系统分析与设计——模糊系统》,楼顺天等,...
  • 组合逻辑控制器与微程序控制器

    千次阅读 2018-06-27 14:55:49
    组合逻辑控制器:指产生控制信号即微命令的部件是用组合逻辑线路来实现的控制器。 优点:速度快 缺点:(1)设计较凌乱,效率较低,检查调试较困难。 (2)不易修改与扩展。微程序控制器:指将程序技术引入到CPU...
  • 一、SpringMVC之控制器控制器方法

    千次阅读 2018-04-22 19:50:17
    一、SpringMVC之控制器控制器方法 二、SpringMVC的控制器方法 1@Controller 声明此类为控制器类,并交给spring容器管理 控制器: 处理请求的类 控制方法:处理请求的方法 2、 @RequestMapping @...
  • 边缘控制器

    千次阅读 2020-03-09 17:15:23
    为了能充分利用接入工业物联网中的工厂,必须将机器和设备接入云服务端,这就需要用到边缘控制器。 绕不开的边缘计算 在介绍边缘控制器之前,需要先了解边缘计算。从图1 工厂构成的示意图来看,未来工厂需要采集大量...
  • 降级域控制器为成员服务器

    万次阅读 2019-12-02 18:48:32
    降级域控制器为成员服务器 1. 运行cmd命令 2. 打开用户和计算机 3. 查看有两台类型为“GC”的计算机,我要降级名称为“VH”的辅助域控制器 4. 服务器管理-管理-删除角色和功能 5. 下一步 6. 下一步 7.双击Active...
  • 控制器管理(控制器之间的切换)掌握: 1、控制器、view的多种创建方式 2、UINavigationController 的简单使用(添加、移除子控制器) 3、UINavigationBar内容的设置 4、控制器的生命周期一、如何创建一个...
  • LCD控制器

    千次阅读 2017-07-26 19:32:18
    2440的lcd控制器可以驱动 STN LCD 和 TFT LCD 本文以较为常见的 TFT LCD 来讲解使用方法: 基础知识:首先, 我们来看下2440的 lcd controller 组成框图: REGBANK: LCD控制器的寄存器组, 含有17个寄存器及
  • 获取当前视图控制器present的控制器

    千次阅读 2015-08-27 11:30:29
    利用present进入的视图控制器,在当前视图控制器里获取present的视图控制器 self.presentingViewController 获取当前视图控制器presented的视图控制器 self.presentedViewController
  • 开源SDN控制器和商用SDN控制器一览

    千次阅读 2017-09-01 15:43:00
    以下是来自IT168收集的2014年可追寻到的开源SDN控制器和商用SDN控制器,此处转载以供大家知悉,更多控制器信息需要大家自己动手去查询和理解。 开源SDN控制器组织(随机排序,仅为了查看便利) 1、组织:NOXRepo 控制...
  • PID控制器开发笔记之十一:专家PID控制器的实现

    万次阅读 多人点赞 2018-09-09 21:30:49
    再接下来的我们将讨论智能PID控制,智能PID控制不同于常规意义下的智能控制,是智能算法与PID控制算法的结合,是基于PID控制器的智能化优化。 在本章我们首先来探讨一下专家PID算法。正如前面所说,专家PID算法是...
  • 微程序控制器之微程序控制器构成

    千次阅读 2017-12-11 11:25:40
    微程序控制器构成
  • 前端控制器和页面控制器

    千次阅读 2014-01-24 10:37:07
    在这种MVC中,并不是令分发器去寻找一个控制器并执行之,而是直接到达视图并且在继续生成视图之前调用相应的控制器。与传统的MVC模式中的前端控制器对应,这种模式称为页面控制器。图3.4和图3.5展示了控制面板的两种...
  • iOS 获取当前控制器的顶层控制器

    千次阅读 2017-01-17 13:27:51
    在开发中,我们可能会遇到类似这样的需求,在模态出...这时就需要我们拿到当前控制器的跟控制器来进行模态弹窗等操作。以下为获取当前显示的控制器的跟控制器方法 - (UIViewController*)topViewController {  ret
  • pop到指定的控制器;pop到上层控制器;返回上上一级控制器
  • 了解一下IO控制器与控制方式

    千次阅读 2020-04-23 16:22:33
    IO控制器 CPU无法直接控制IO设备的机械部件,因此IO设备还要有个电子部件作为CPU和IO设备机械部件之间的“中介”,用于实现CPU对设备的控制。 这个电子部件就是IO控制器,又称为设备控制器。CPU可控制IO控制器,IO...
  • 一、磁盘控制器  硬盘接口包含物理接口和逻辑接口。  物理接口:硬盘和磁盘控制器连接的接口。  逻辑接口:指令系统。如SCSI指令集和ATA指令集。  磁盘控制器用来向驱动器的控制电路发送指令,从而控制磁盘...
  • 前端控制器模式

    千次阅读 2019-09-25 20:02:19
    前端控制器模式(Front Controller Pattern)是用来提供一个集中的请求处理机制,所有的请求都将由一个单一的处理程序处理。该处理程序可以做认证/授权/记录日志,或者跟踪请求,然后把请求传给相应的处理程序。以下...
  • 关于多级控制器和分层控制器希望大家不要被名称所困扰,这两个概念我更希望通过目录结构的改变来给大家说明。只是控制器所在的位置不同而已。 点击进入视频教程分层控制器中所定义的控制器其实是不能被URL直接访问...
  • 前面我们发布了一系列PID控制器相关的文章,包括经典PID控制器以及参数自适应的PID控制器。这一系列PID控制器虽说实现了主要功能,也在实际使用中取得了良好效果,但还有很多的细节部分可以改进以提高性能和灵活性。...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 300,678
精华内容 120,271
关键字:

控制器