15.4.11 逻辑指令
15.4.11.3 WaitUntil
说明: 程序等待某个条件成立,若超时,则将超时标志置 true,结束等待继续向下执行。
定义:
WaitUntil(cond, \MaxTime, \TimeFlag);
-
Cond:bool 类型逻辑表达式。 -
MaxTime:超时等待时间,可选参数。单位 s,使用 int 或 double 类型。 -
TimeFlag:超时标志位,若超时则置 true,可选参数。使用 bool 类型变量。
示例:
例1
WaitUntil (di2 == true);
表示等待 di2 信号值为 true,然后才开始执行后面的语句。
例2
WaitUntil (di2 == true, 5);
表示等待 di2 信号值为 true,若等待超过 5s,di2 信号依然为 false,则执行后面的语句。
例3
Bool flag = false;
WaitUntil (di2 == true, 5, flag);
表示等待 di2 信号值为 true;若等待超过 5s,di2 信号依然为 false,则将 flag 置为 true,然后才开始执行后面的语句;若在 5s 内 di2 变为 true,则 flag 置为 false。可以将 flag 用于后续的逻辑判断。
15.4.11.4 Break
说明: 跳出当前循环。在 RL 语言中在 WHILE 循环中使用,当 WHILE 循环执行到 Break 时,不管 WHILE 的 CONDITION 如何,都会直接跳出 WHILE 循环。
示例:
例 1
VAR int counter = 0;
WHILE(1)
IF(counter == 5)
break;
ENDIF
counter++;
ENDWHILE
程序在执行到 counter 等于 5 时会跳出 WHILE 循环。
15.4.11.5 IF…Else if…Else
说明: 条件判断语句。
示例:
例 1
IF(condition1)
// a
Else if(condition2)
// b
Else if(condition3)
// c
Else
// d
Endif
condition1 成立时执行逻辑 a,condition2 成立时执行逻辑 b,以此类推。
15.4.11.6 Goto
说明: Goto 语句允许把指针跳转到被标记的语句。
示例:
int a = 0;
int b = 9;
Goto end;
print(a);
end:;
print(b);
先定义两个变量 a 和 b,然后用 print 函数打印两句话,直接用 Goto 语句强制跳转到打印 b 语句的 end 标记位置,此时 a 的打印就不会执行了。
15.4.11.7 For
说明: For 循环允许您编写一个执行指定次数的循环控制结构。
示例:
例1
For(int i from 1 to 10)
Print(“i=%d\n”, i);
endfor
该程序把 i 从 1 到 9 每次加 1 依次打印 9 次。
例2
For(int i from 1 to 10 step 3)
Print(“i=%d\n”, i);
Endfor
该程序把 i 从 1 到 10 每次加 3 依次打印 3 次。 补充说明: Continue 和 Break 可以用来控制 For 的流程,详细操作见 Continue 和 Break 指令说明。
15.4.11.8 Continue
说明: 跳出本次循环。继续从循环起始处执行下条语句,但不退出循环体,仅仅结束本次循环。
示例:
例 1
VAR int count = 0
WHILE(1)
count++
IF(count==1)
Continue
Else
Break;
MoveAbsJ(j10,v500,fine,tool1);
Endif
ENDWHILE
// MoveAbsJ 的代码将不会被执行到。
15.4.11.9 Inzone
说明: 该指令和 SetDO 或者 modbus、cclink 等 IO 操作或指令配合使用,可保证信号在确定的点位触发,不会被前瞻指针提前触发。
示例:
MoveL(p1);
MoveL(p2);
Inzone
SetDO(dox, true);
print(123);
EndInzone
MoveL(p3);
补充说明:
在示例中,使用了一个 Inzone 指令,解释器前瞻到 Inzone 之后,并不会立即执行,而是生成了一个附加函数,函数内容是 SetDO 以及 print 指令,这个附加函数会在运动指令 move(p2) 完成之后生效。
1、如果 p2、p3 两条运动指令之间存在转弯区,则附加函数会在机器人进入两段运动的转弯区的时刻开始执行。
2、如果没有转弯区,则附加函数会在机器人到达 p2 的时刻开始执行。
15.4.11.10 While
说明: While 循环允许您编写一个在条件满足前不断执行的循环控制结构。
示例:
例 1
int count = 0;
while(count < 10)
count++;
print(count);
endwhile
该程序实现一个 count 从 0 到 10 每次加 1 并打印的循环。
补充说明:Continue 和 Break 可以用来控制 While 的流程,详细操作见 Continue 和 Break 指令说明。
15.4.11.11 Pause
说明: 暂停程序运行。程序会在 pause 语句的前一句执行完毕后进入暂停状态,必须使用示教器点击运行或者通过外部程序启动信号才可恢复程序运行。
|
15.4.11.12 try/catch
说明: try-catch 指令是一种 RL 语言的错误处理机制,try 到 catch 指令中间的指令,如果出错后,程序会将执行错误转换为错误信息集合 "e" 并从 catch-endtry 的代码块继续运行。
定义:
try
// do something
catch(error e)
print(e);
endtry;
举例:从网络链接读数据是很有可能失败的指令,但是此时不希望机器人停机,可以用 try-catch 将错误捕获并通过RL编程处理。
详细说明:
error 类型说明:error 是一个结构体,一共有四个参数:
* file:string,错误发生文件名。
* line:int,错误行。
* num:int,错误码。
* reason:string,错误原因。
error结构体可以通过print指令直接打印。
//error data
...
catch(error e)
print(e.line);
print(e.num);
print(e.reason);
print(e);
endtry
示例:
例1
ReadOnce:;
Try
Double xyz[3] = ReadDouble(3, timeout, socketname);
Robtarget_0.trans.x = xyz[1];
Robtarget_0.trans.y = xyz[2];
Robtarget_0.trans.z = xyz[3];
MoveL (Robtarget_0, v2000, fine, tool0);
Catch(error e)
SendString(“Recv rob xyz error”, socketname);
Goto ReadOnce;
endtry
该程序实现了一个简单的应用场景,使用通信指令 ReadDouble 从 TcpSocket 读取一个三维数组作为运动点位的 xyz 参数,然后使用 MoveL 指令运动到对应笛卡尔点。
如果没有使用 try/catch 指令并且从 TcpSocket 收到点位是错误数据,则机器人会报错“超出运动范围”或者“规划错误”,并且停止程序的运行。
如果使用了 try/catch 指令,虽然依然会报告运动指令错误,但是程序不会停止,而是跳转到 catch 到 endtry 的代码段,执行用户想要的错误处理。本样例中就是通过 SendString 告诉 Socket 上位机收到的点位错误,再由上位机决定如何处理,并执行 goto 指令重新执行 ReadDouble 等待下一次的位置。
例2
re_read:;
try
opendev("conn_name");
string_res = readstring("conn_name");
catch (error e)
if (e.num == xxx)
// 某种可处理的错误不暂停
goto re_read;
else
print(e);
Pause;
endif
endtry
|
try/catch 能够处理的错误类型及标准错误码:
分类 |
出错指令 |
说明 |
error.num |
error.reason |
默认错误 |
未分配专属错误码的指令 |
-1 |
未知错误 |
|
串口相关指令 |
串口不存在时 |
-1 |
未知错误 |
|
运动相关指令 |
MoveXX, Search, TrigL 等;AccRamp, HomeSet 等运动参数设置 |
运动坐标的工具、工件错误;运动速度错误;运动负载错误;超出运动范围;规划错误;遇到奇异点等 |
-1 |
未知错误 |
网络指令 |
OpenDev |
网络链接的端口错误 |
-1 |
未知错误 |
所有网络指令 |
通过RL操作外部通讯的连接 |
-1 |
未知错误 |
|
计算、逻辑指令 |
CalcJointT, CalcRobT, CRobT, CJointT, ClkStop, GOTO |
控制器内部错误 |
-1 |
未知错误 |
外设控制(Jodell系列/RM系列) |
JodellGripInit, JodellSuckInit, JodellSuckStatus, RMRGMGripPosMove, RMRGMGripTrqMove, RMRGMGripStatus, RMRGMResetErr, RMCGripPosMove, RMCGripTrqMove, RMCGripStatus, RMCResetErr, RMRGMGripInit, RMCGripInit |
外设通讯异常 |
-1 |
未知错误 |
激光控制 |
Laser所有指令 |
激光焊接已关闭 |
-1 |
未知错误 |
码垛控制 |
TrayUpdate, TrayCount, PalletUpdate, PalletLayerCount, PalletWobjCount, SolarVisionExec |
与上位机数据收发错误 |
-1 |
未知错误 |
寄存器控制 |
ReadRegByteByName |
读取数据失败 |
-1 |
未知错误 |
四轴锁定 |
SingAreaLockAxis4 |
位姿错误,无法开启四轴锁定功能 |
-1 |
未知错误 |
解释器内部错误 |
绝大部分指令的参数类型、数量错误 |
-1 |
XXX参数错误 |
|
解释器内部错误 |
0 |
|||
网络指令/串口指令 |
OpenDev |
连接到服务器失败 |
101 |
OpenDevConn失败 |
OpenDev |
机器人作为服务端开启失败 |
102 |
OpenDevServer失败 |
|
GetSocketConn |
SocketConn对应的连接未建立 |
103 |
GetSocketConn失败,连接不存在 |
|
GetSocketConn |
获取SocketConn结构体的名字是一个服务器 |
104 |
GetSocketConn失败,对象是SocketServer |
|
GetSocketServer |
GetSocketServer失败,服务器不存在 |
105 |
GetSocketServer失败,服务器不存在 |
|
OpenDev |
开启连接输入参数错误,变量列表无对应连接 |
106 |
OpenDev失败,使用不存在的对象 |
|
SocketAccept |
输入参数不是服务器名称 |
107 |
SocketAccept(server)指令需要服务器名称 |
|
GetSocketConn |
获取SocketConn结构体的名字错误 |
108 |
GetSocketConn(conn)不存在的SocketConn |
|
GetSocketServer |
获取SocketConn结构体的名字错误 |
109 |
GetSocketConn(server)不存在的SocketServer |
|
ReadBit |
指令输入参数错误 |
110 |
ReadBit必须读取8的整数倍数 |
|
ReadDouble |
指令输入参数错误 |
111 |
ReadDouble指令超出预设范围(0,4096] |
|
ReadInt |
指令输入参数错误 |
112 |
ReadInt指令超出预设范围(0,4096] |
|
ReadByte |
指令输入参数错误 |
113 |
ReadByte指令超出预设范围(0,4096] |
|
ReadBit, ReadDouble, ReadInt, ReadByte, ReadString |
输入的时间太长 |
114 |
ReadXX指令时间超出预设范围(0,86400] |
|
ReadBit, ReadDouble, ReadInt, ReadByte, ReadString |
连接断开或者读取数据错误 |
115 |
Read指令失败 |
|
ReadDouble |
超出限定时间 |
116 |
ReadDouble指令超时 |
|
ReadInt |
超出限定时间 |
117 |
ReadInt指令超时 |
|
ReadString |
超出限定时间 |
118 |
ReadString指令超时 |
|
ReadBit |
超出限定时间 |
119 |
ReadBit指令超时 |
|
ReadByte |
超出限定时间 |
120 |
ReadByte指令超时 |
|
SendString |
指令超时或者连接断开 |
121 |
SendString指令超时或者连接断开 |
|
SendByte |
指令超时或者连接断开 |
122 |
SendByte指令超时或者连接断开 |
|
传送带跟踪指令 |
WaitObj |
执行指令时,工件已经越过启动窗口,无法跟踪 |
123 |
Out StartWindow |
WaitObj |
等待跟踪工件超时 |
124 |
Out WaitTime |
|
WaitObj |
重复跟踪工件 |
125 |
Connected Twice |
|
开启跟踪后可能发生 |
跟踪过程超出工作区域抛出异常 |
126 |
Out MaxDistance |
15.4.11.13 SwitchCase
说明: SwitchCase 指令跟 IF 指令类似,是根据输入的变量条件进行流程控制的指令。RL 解释器将根据输入的变量(condition)依次与 Case 字段的变量进行比较:
* 如果两个变量相等,解释器将进入对应 Case 的代码分支,并且不再进行后续比较。不会进入其他代码分支;
* 如果所有条件都不满足,则会进入 Default 分支;
* 如果没有 Case 条件匹配且没有 Default 分支,则不会进入任何分支,Switch 指令结束;
* Case 指令可以输入多个条件(见指令结构 Case C1,C12,C13 和示例 1)。
定义:
Switch(condition)
Case C1, C12, C13:
Functions1();
Case C2:
Functions2();
Default:
DefaultFunction();
EndSwitch
示例:
例 1
reg_int 是一个寄存器变量,上位机(PLC)会通过相关寄存器协议(如 modbus、cclink)更新变量的数值,生产工程希望机器人根据寄存器的数值,执行对应的函数分支(比如走不通的运动轨迹),如果寄存器输入 1,2,3 则执行 A 函数,如果输入 4,5,6 则执行 B 函数,如果不符合上述条件,则进入 Default 分支执行 C 函数。
Switch(reg_int)
Case 1,2,3:
FunctionsA();// 机器人走功能 A 相关点位
Case 4,5,6:
FunctionsB();// 机器人走功能 B 相关点位
Default:
FunctionC(); // 无指定输入执行 C 功能
EndSwitch