2. KRL程序基本骨架

KRL(KUKA Robot Language)程序并不是“写几行运动指令就能跑”的脚本,它必须遵循一套固定的语法骨架。理解这套骨架,是后续所有编程、调试和模块化开发的前提。本节从最小的可运行结构出发,逐步展开程序入口、模块划分、注释规范,并给出一个可以直接在示教器上验证的完整示例。

一、DEF/END:KRL程序的“外壳”

每一个KRL程序文件都以 DEF 开头、以 END 结尾。这两个关键字不是可选项,而是语法强制要求。它们共同界定了一个“程序块”的边界,控制器只识别这对边界之间的内容。

基本形式如下:

DEF MY_PROGRAM()
  ; 程序体
END

其中 DEF 后面跟程序名,程序名由字母、数字和下划线组成,必须以字母开头,不能使用KRL保留字(如 IF、FOR、WAIT 等)。程序名后的圆括号用于参数列表,无参数时也必须保留空括号。这一点与很多高级语言不同,初学者常因漏写括号导致编译报错。

END 必须独占一行,且不能带分号或其它符号。控制器在扫描到 END 时认为该程序块结束,后续内容若存在则会被视为下一个程序块或语法错误。

在示教器上新建程序时,系统会自动生成 DEF 和 END 框架,但手工修改时务必确认两者成对出现。一个常见的排障经验是:如果程序无法被选中运行,首先检查 DEF 行是否被误删或程序名是否与文件名不一致。

二、程序入口与执行顺序

KRL没有像C语言那样显式的 main 函数。当你在示教器上选中某个程序并按下启动键时,控制器会从该程序的 DEF 行之后的第一条可执行语句开始,自上而下顺序执行,直到遇到 END 或 RETURN。

这意味着“程序入口”就是程序体的第一条语句。因此,程序开头的初始化语句(如设置速度、打开工具、复位信号)必须放在最前面,否则后续运动指令可能使用未初始化的默认值。例如,若未先设置 $VEL_CP,机器人会以系统默认的全局速度运行,这在调试阶段非常危险。

执行顺序遵循三个原则:

  • 顺序性:语句按书写顺序逐条执行,运动指令会阻塞后续语句直到运动完成(除非使用 PTP 的 C_DIS 等特殊参数)。
  • 单入口:一个程序只有一个入口,即 DEF 后的第一条语句。
  • 显式返回:若需提前结束,使用 RETURN,但 END 仍是必须存在的语法终点。

三、模块化组织:把大程序拆成小单元

实际工程中,一个完整的机器人任务往往包含回原点、取件、检测、放件、报警处理等多个阶段。如果全部写在一个 DEF/END 里,程序会变得难以阅读和维护。KRL的模块化手段主要有两种:子程序和函数。

子程序本质上就是另一个 DEF/END 块,通过 CALL 或直接写程序名调用。例如:

DEF MAIN()
  PTP HOME
  WAIT FOR $IN[1] == TRUE
  PICK_PART()
  PLACE_PART()
END

DEF PICK_PART()
  ; 取件动作
END

DEF PLACE_PART()
  ; 放件动作
END

这种组织方式让主程序只保留流程逻辑,具体动作封装在子程序中。修改取件姿态时只需改 PICK_PART,不会影响主流程。需要注意的是,子程序必须与主程序在同一个文件内,或者通过 DEF 文件独立存放并由控制器自动加载。

函数与子程序的区别在于函数有返回值,使用 DEFFCT 定义,以 ENDFCT 结束。例如计算两点距离:

DEFFCT REAL DIST(A:IN, B:IN)
  REAL A, B
  RETURN A - B
ENDFCT

模块化不是把程序切得越碎越好。一个实用的判断标准是:如果一个动作序列在多个任务中重复出现,或者它对应一个独立的物理动作(如“打开夹爪”),就值得封装成子程序。

四、注释规范:让程序可读

KRL使用分号 ; 作为注释符,从分号到行尾的内容都会被控制器忽略。注释不参与执行,但直接影响程序的可维护性。

推荐的做法是:

  • 在 DEF 行上方或下方用注释说明程序功能、作者、日期和版本。
  • 在每个子程序调用前用注释说明该步骤的目的,而不是重复指令本身。
  • 对关键参数(如速度、等待条件、工具号)用注释标注取值范围或来源。
  • 避免在行尾堆砌过长注释,保持每行简洁。

例如:

DEF MAIN()
  ; 功能:抓取工件并放置到检测台
  ; 版本:V1.2  日期:2024-06-01
  PTP HOME                    ; 回原点,使用全局速度
  $VEL_CP = 0.2               ; 降低CP速度至0.2m/s,便于观察
  WAIT FOR $IN[1] == TRUE     ; 等待工件到位信号
  PICK_PART()                 ; 调用取件子程序
  PLACE_PART()                ; 调用放件子程序
END
注释中不要使用中文全角分号“;”,控制器只识别半角 ;。此外,注释不能嵌套,分号后的所有内容都会被忽略。

五、第一个可运行程序:从骨架到动作

下面给出一个完整的、可在示教器上运行的最小示例。它包含初始化、等待、调用子程序和结束四个部分,所有参数均为教学示例值,实际运行时需根据现场情况调整。

DEF FIRST_RUN()
  ; 教学示例:第一个可运行程序
  ; 功能:回原点,等待信号,执行一次取放动作
  ; 注意:以下速度与位置为示例值,请根据实际工况修改

  $VEL_CP = 0.3               ; 设置CP速度为0.3m/s
  $ACC_CP = 50                ; 设置CP加速度为50%

  PTP HOME                    ; 回原点
  WAIT FOR $IN[1] == TRUE     ; 等待工件到位

  PICK_PART()                 ; 取件
  PLACE_PART()                ; 放件

  PTP HOME                    ; 返回原点
END

DEF PICK_PART()
  ; 取件子程序:示例位置
  PTP XHOME
  LIN XPICK
  WAIT FOR $IN[2] == TRUE     ; 等待夹爪闭合确认
  LIN XPICK_UP
END

DEF PLACE_PART()
  ; 放件子程序:示例位置
  PTP XPLACE
  LIN XPLACE_DOWN
  $OUT[1] = TRUE              ; 打开夹爪
  WAIT TIME 0.5               ; 等待0.5秒
  LIN XPLACE_UP
END

运行前需要确认:HOME、XHOME、XPICK、XPLACE 等点位已在示教器中示教并命名;$IN[1]、$IN[2] 已正确映射到实际输入信号;$OUT[1] 已连接到夹爪控制阀。启动后,机器人应先回原点,等待输入信号,然后依次执行取件和放件,最后回到原点。若中途停止,可观察示教器上的当前指令行号,判断是等待条件未满足还是运动指令被中断。

KRL程序骨架与模块化调用关系 主程序 FIRST_RUN DEF FIRST_RUN() $VEL_CP = 0.3 ; 初始化 PTP HOME ; 回原点 WAIT FOR $IN[1] == TRUE CALL PICK_PART() CALL PLACE_PART() PTP HOME ; 返回原点 END 子程序 PICK_PART PTP XHOME LIN XPICK WAIT FOR $IN[2] == TRUE 子程序 PLACE_PART PTP XPLACE LIN XPLACE_DOWN $OUT[1] = TRUE ; 打开夹爪 调用 调用 DEF/END 界定程序块边界;主程序顺序执行,通过 CALL 进入子程序,子程序执行完毕后返回主程序继续

把这个程序在示教器上运行一遍,观察机器人是否按“回原点→等待→取件→放件→回原点”的顺序动作。如果某一步没有执行,优先检查对应的等待条件是否满足、点位是否已示教、输出信号是否已连接。这个最小骨架可以反复复用:后续增加新动作时,只需在 END 之前插入新的子程序调用,并在文件末尾添加对应的 DEF/END 块即可。