如何在 KRL 中优雅地使用 IF-THEN-ELSE 语句

目录 Content
[hide]

一、问题背景

IF 是 KUKA 机器人编程语言 KRL 使用的语句,可以判断当一个条件满足时执行某种结果,而不满足时执行另一种结果。它的最大好处是符合自然语言习惯,易于阅读。

例如下面代码:

IF (input==TRUE) THEN
    output = TRUE
ELSE
    output = FALSE
ENDIF

它表示:当输入变量input为1时,输出变量output输出值为1,当输入变量input为0时,输出变量output变为0。

如果有两个输入输入条件串联的话,可以这么写

IF ((input1==TRUE) AND  (input2==TRUE)) THEN
    output = TRUE
ELSE
    output = FALSE
ENDIF

它表示:只有当input1和input2都为1的话,output才会为1,否则为0。

如果有三个输入条件串联的话呢,你会说可以这么写:

IF ((input1==TRUE) AND  (input2==TRUE) AND  (input3==TRUE)) THEN
    output = TRUE
ELSE
    output = FALSE
ENDIF

如果有20个输入条件串联呢 ,你会说这么写么:

IF ((input1==TRUE) AND  (input2==TRUE) AND  (input3==TRUE) AND  (input4==TRUE) AND  (input5==TRUE) AND  (input6==TRUE) AND  (input7==TRUE) AND  (input8==TRUE) AND  (input9==TRUE) AND  (input10==TRUE) AND  (input11==TRUE) AND  (input12==TRUE) AND  (input13==TRUE) AND  (input14==TRUE) AND  (input15==TRUE) AND  (input16==TRUE) AND  (input17==TRUE) AND  (input18==TRUE) AND  (input19==TRUE) AND  (input20==TRUE)) THEN
    output = TRUE
ELSE
    output = FALSE
ENDIF

请重新审视上面这段代码,它易于阅读么,感觉是不是眼前一团糟,如果想更改其中一个条件,是不是定位这个变量很费劲?

那么,问题来了:要怎样组织这20个条件的IF语句才优雅呢? LT 打算将这个问题发到网上,看看大家都有怎样的妙招来解决这个问题?

二、网上众筹

于是 LT 就在 weibo 上@一些朋友,看看他们如何看待这个问题

@DAVIDROBOT_INDUSTRY: IF 是高级语言编程中使用的语句,可以判断当一个条件满足时执行某种结果,而不满足时执行另一种结果。……如果有20个输入条件串联呢 ,你会说这么写么…O网页链接 @linuxsand @拉面小新 @shumaojie @Huigens @机械葫芦娃 @工控人-在路上 @于仁颇黎 各位大侠,请发表发表看法?

这一部分将是众筹的解决方案,这样,解决问题的思路将不会仅局限于个人,各种想法可以交叉碰撞。

收到 @机械葫芦娃 的回复

@机械葫芦娃: 个人想法:for遍历20个变量,只要有一个变量是false,就输出”false”,如果没有false,就输出true【for(i in 20个变量 ) if i==false than output=false】.或者用位运算(一个字节8个bit),每个变量占一个bit,按位异或:input ^ test【如同 01101101 xor 1111111】结果不==0就输出false。#求其它更好解答#

收到 @Huigens 的回复

 @Huigens:我仍然会这么写,但会排列整齐,该回车换行就换行嘛,一样可以赏心悦目
@DAVIDROBOT_INDUSTRY:回复@Huigens:假如不支持换行呢
@Huigens:回复@DAVIDROBOT_INDUSTRY:你…太险恶了竟然剥夺回车换行权利。那我就用cross connection ,每6个做成一个组合变量,然后将新创建的4个组合变量作为IF条件
@DAVIDROBOT_INDUSTRY:回复@Huigens:这是个办法[哈哈]

收到 @shumaojie 的回复

@shumaojie:回复@机械葫芦娃:同意。一个32位bit,每个赋值,然后转化为double,看看是否大于零就可以了。

收到 @linuxsand 的回复

@linuxsand:和葫芦娃兄的第一种想法相同,但是实现上我不会选择bit那么细粒度的办法,因为也许今后代码会有比我更业余的人来维护;我会用一眼就能看明白但往往是性能较差的办法,让后来者把脑力集中理解到业务逻辑上。

收到 @AB_机器人 的回复

@AB_机器人:如果做现场程序的的话,现场的变量应该都可以分类,比如和气体相关的,和安全相关的传感器信号,和标定相关的,分类操作,20个变量的可以分作几类,这样便于后面的人维护;如果是同一类信号,如果吸盘数据,可以按区域分成几组,按组操作判别信号变量。如果是我自己写程序,我倾向于位操作

收到 @工控人-在路上 的回复

@工控人-在路上:如果是我,肯定用递归来写 $i=0; $var=array(1,1,1,1,1,0…);//判断条件,输入0或1,有多少输入多少 function judge($j,$a,$var){ if ($a==true){$j++; if($j>=20){//可以写成自动数组判断 return 1; } return(judge($j,$var[$j],$var)); }else{ return 0; }大致这样,没测试

收到 @于仁颇黎 的回复

@于仁颇黎:用二进制组合变成10进制数如何?

 

三、我的经历

IF 语句,其实不仅仅局限于C++ 编程。在采用C++语言时,如果有很多个串联条件,LT 的做法确实是采用回车换行的做法,这样,阅读代码比较清晰,就像 @Huigens  所说。

    if(input1 == true
        && input2 == true
        && input3 == true
        && input4 == true
        ){
        //
        output = true;
    }else{
        //
        output = false;
        }

本文开篇提到的问题,源于LT 在 KUKA 机器人上的编程,KUKA机器人采用的编程语言是KRL。最初,LT确实写了3、4个AND在一起的条件判断,不过,也还好,阅读也还清晰。

但是关键点在于两点:

  • KRL 代码不支持回车换行,所以不能像 C++ 一样通过换行来使代码清晰。
  • KUKA机器人示教盒显示屏一行显示的字数有限,这样长代码就会被自动换行,看起来就不分明。即使在电脑上查看也不分明。后期修改不方便。

于是,LT 想把条件分开,于是就有了下面的变形,举例来说,如果有3个条件串联

IF (input1==TRUE) THEN
    IF(input2==TRUE) THEN
        IF(input2==TRUE)THEN
            ;the last 
            output=TRUE
        ELSE
            output==FALSE
        ENDIF
    ELSE
        output==FALSE
    ENDIF
ELSE
    output = FALSE
ENDIF

如果input1满足,进而再判断input2,如此类推。如果要新增加条件,只需要在后面添加类似的代码就行了,这样在有限的屏幕上能看到大部分代码。

后面一个应用,LT 确实按照这个思路开始写程序了,比如下面这个样子:

DEF TEST_IF_10( )
BOOL input[14]
BOOL output
;
INT I
FOR I =1 TO 14
    input[i]=FALSE
ENDFOR
;
IF(input[1]==TRUE) THEN
    IF(input[2]==TRUE)THEN
        IF(input[3]==TRUE)THEN
            IF(input[4]==TRUE)THEN
                IF(input[5]==TRUE)THEN
                    IF(input[6]==TRUE)THEN
                        IF(input[7]==TRUE)THEN
                            IF(input[8]==TRUE)THEN
                                IF(input[9]==TRUE)THEN
                                    IF(input[10]==TRUE)THEN
                                        IF(input[11]==TRUE)THEN

                                        ELSE
                                            output=FALSE
                                        ENDIF
                                    ELSE
                                        output=FALSE
                                    ENDIF
                                ELSE
                                    output=FALSE
                                ENDIF
                            ELSE
                                output=FALSE
                            ENDIF
                        ELSE
                            output=FALSE
                        ENDIF
                    ELSE
                        output=FALSE
                    ENDIF
                ELSE
                    output=FALSE
                ENDIF
            ELSE
                output=FALSE
            ENDIF
        ELSE
            output=FALSE
        ENDIF
    ELSE
        output=FALSE
    ENDIF
ELSE
    output=FALSE
ENDIF

END

虽然看起来有点怪怪的,但是还好,一个屏幕能看到11个条件,如果缩进使用2个空格,兴许还可以更多。下面的图片就是示教盒上看到的样子(取消了换行)。

TEST_IF_10

事情到此似乎结束了,可是当 LT 保存后,出现了报错!意思是嵌套达到最大深度了!

TEST_IF_10_ERRLT 当时就惊呆了,原来 KRL 还有嵌套深度的限制!于是 LT 又重新测试确认了下,没错,IF-ELSE 嵌套只能10层,到第11层就会报错,也就是说,采用目前这个结构形式,只能写10个条件。那11个条件以后的怎么办?显然,问题没有解决。

后来 robotforum 浏览时,忽然看到 SkyeFire 一种奇怪的写法,登时恍然大悟,加以吸收改善。这种写法的原理就是,将条件拆散!回顾一下上面的代码,IF-ELSE其实就是只判断了结果,如果IF后面只有一个结果,那么代码就简洁了。于是,有了下面的代码结构:

DEF TSET_IF( )
BOOL input[14]
BOOL output
;
INT I
FOR I =1 TO 14
    input[i]=FALSE
ENDFOR
;
output = TRUE
output = output AND input[1]
output = output AND input[2]
output = output AND input[3]
output = output AND input[4]
output = output AND input[5]
output = output AND input[6]
output = output AND input[7]
output = output AND input[8]
output = output AND input[9]
output = output AND input[10]
output = output AND input[11]
output = output AND input[12]
output = output AND input[13]
output = output AND input[14]
;

END

在示教器界面上看起来很分明! 完美!在后面再加上 20个条件也不成问题!

TEST_IF至此,LT 觉得算是告一段落。

四、深度分析

上面最后一种写法,其实与前面网友的想法一致,是对某个位进行操作,再把所有的位的操作集合起来再进行判断,只不过上面的写法更为特例而已。

@Huigens 提出的,就是把多个信号拆分,并利用其它并行处理的程序对其进行处理后再组合。也是一个很常见的处理方法。

在处理复杂条件时,最好把条件分类拆分判断,再将各个组合的结果再次组合,不要试图在一行代码里面写完所有的条件。

感谢众网友的思想火花!

五、扩展阅读

关键字: KRL, IF-ELSE, IF, 嵌套

4 thoughts on “如何在 KRL 中优雅地使用 IF-THEN-ELSE 语句

    • 这个也是没有办法的办法。用的时候要自己组织起始逻辑和逐行逻辑关系

  1. 问一下您,KUKA中编程时可以同时给两个信号发脉冲信号吗,我改写试了很多次,都不行

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.