[AB] 【机器人编程探讨】如何优雅地使用 IF-THEN-ELSE 语句!

[复制链接]
查看48982 | 回复0 | 2024-5-1 21:36:07 | 显示全部楼层 |阅读模式
一、问题背景


二、网上众筹

三、我的经历

四、深度分析

五、扩展阅读

一、问题背景

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

例如下面代码:
1IF (input==TRUE) THEN
2    output = TRUE
3ELSE
4    output = FALSE
5ENDIF

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

如果有两个输入输入条件串联的话,可以这么写
1IF ((input1==TRUE) AND  (input2==TRUE)) THEN
2    output = TRUE
3ELSE
4    output = FALSE
5ENDIF

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

如果有三个输入条件串联的话呢,你会说可以这么写:
1IF ((input1==TRUE) AND  (input2==TRUE) AND  (input3==TRUE)) THEN
2    output = TRUE
3ELSE
4    output = FALSE
5ENDIF

如果有20个输入条件串联呢 ,你会说这么写么:
1IF ((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
2    output = TRUE
3ELSE
4    output = FALSE
5ENDIF

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

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

二、网友的回答

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


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  所说。
01if(input1 == true
02    && input2 == true
03    && input3 == true
04    && input4 == true
05    ){
06    //
07    output = true;
08}else{
09    //
10    output = false;
11    }

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

但是关键点在于两点:


    KRL 代码不支持回车换行,所以不能像 C++ 一样通过换行来使代码清晰。

    KUKA机器人示教盒显示屏一行显示的字数有限,这样长代码就会被自动换行,看起来就不分明。即使在电脑上查看也不分明。后期修改不方便。

于是,LT 想把条件分开,于是就有了下面的变形,举例来说,如果有3个条件串联
01IF (input1==TRUE) THEN
02    IF(input2==TRUE) THEN
03        IF(input2==TRUE)THEN
04            ;the last
05            output=TRUE
06        ELSE
07            output==FALSE
08        ENDIF
09    ELSE
10        output==FALSE
11    ENDIF
12ELSE
13    output = FALSE
14ENDIF

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

后面一个应用,LT 确实按照这个思路开始写程序了,比如下面这个样子:
01DEF TEST_IF_10( )
02BOOL input[14]
03BOOL output
04;
05INT I
06FOR I =1 TO 14
07    input=FALSE
08ENDFOR
09;
10IF(input[1]==TRUE) THEN
11    IF(input[2]==TRUE)THEN
12        IF(input[3]==TRUE)THEN
13            IF(input[4]==TRUE)THEN
14                IF(input[5]==TRUE)THEN
15                    IF(input[6]==TRUE)THEN
16                        IF(input[7]==TRUE)THEN
17                            IF(input[8]==TRUE)THEN
18                                IF(input[9]==TRUE)THEN
19                                    IF(input[10]==TRUE)THEN
20                                        IF(input[11]==TRUE)THEN
21
22                                        ELSE
23                                            output=FALSE
24                                        ENDIF
25                                    ELSE
26                                        output=FALSE
27                                    ENDIF
28                                ELSE
29                                    output=FALSE
30                                ENDIF
31                            ELSE
32                                output=FALSE
33                            ENDIF
34                        ELSE
35                            output=FALSE
36                        ENDIF
37                    ELSE
38                        output=FALSE
39                    ENDIF
40                ELSE
41                    output=FALSE
42                ENDIF
43            ELSE
44                output=FALSE
45            ENDIF
46        ELSE
47            output=FALSE
48        ENDIF
49    ELSE
50        output=FALSE
51    ENDIF
52ELSE
53    output=FALSE
54ENDIF
55
56END

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



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



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

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

01

DEF TSET_IF( )

02

BOOL input[14]

03

BOOL output

04

;

05

INT I

06

FOR I =1 TO 14

07

    input=FALSE

08

ENDFOR

09

;


11

output = output AND input[1]

12

output = output AND input[2]

13

output = output AND input[3]

14

output = output AND input[4]

15

output = output AND input[5]

16

output = output AND input[6]

17

output = output AND input[7]

18

output = output AND input[8]

19

output = output AND input[9]

20

output = output AND input[10]

21

output = output AND input[11]

22

output = output AND input[12]

23

output = output AND input[13]

24

output = output AND input[14]

25

;

26


27

END

在示教器界面上看起来很分明! 完美!在后面再加上 20个条件也不成问题!至此,LT 觉得算是告一段落。


四、深度分析

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

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

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





本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册哦

x
您需要登录后才可以回帖 登录 | 注册哦

本版积分规则