1542 lines
38 KiB
Markdown
1542 lines
38 KiB
Markdown
# 通用机器人编程语法规范
|
||
|
||
版本:0.1
|
||
适用范围:离线编程、虚拟控制器、虚拟调试、多品牌后处理
|
||
目标品牌:ABB RAPID、FANUC TP/LS/KAREL 语义、KUKA KRL
|
||
|
||
## 1. 设计目标
|
||
|
||
本规范定义一种用于离线编程和虚拟调试的通用机器人程序语言,暂定名为 GRL,Generic Robot Language。GRL 不是复制某一家机器人厂商语言,而是抽象 ABB、FANUC、KUKA 等主流工业机器人共同具备的程序语义,形成稳定、可解析、可仿真、可自动生成、可后处理的中性机器人程序。
|
||
|
||
核心目标:
|
||
|
||
1. 支持离线编程的完整流程:目标点、路径、工艺、IO、等待、流程控制、报警、仿真执行、报告和后处理。
|
||
2. 方便由规划点、CAD 曲线、工艺模板、AI 规划器自动生成程序。
|
||
3. 方便转换为 ABB RAPID、FANUC LS/TP 风格文本、KUKA KRL。
|
||
4. 方便反向导入品牌程序,恢复为统一 IR、GRL 和 OLP 对象模型。
|
||
5. 程序文本稳定、可读、可 diff,便于版本管理。
|
||
6. 语义确定,编译后能生成统一可执行 IR,虚拟控制器不依赖品牌控制器细节。
|
||
|
||
非目标:
|
||
|
||
1. 不追求完全复刻某一品牌控制器所有系统变量和内部调度细节。
|
||
2. 不直接作为真实机器人安全运行的唯一依据,后处理输出必须经过品牌控制器验证和现场低速试运行。
|
||
3. 不把 CAD、碰撞检测、机器人运动学全部写入语言本身;这些由 OLP 模型和仿真内核承担。
|
||
|
||
## 2. 对标原则
|
||
|
||
### 2.1 品牌能力映射
|
||
|
||
| 能力 | ABB RAPID | FANUC TP/LS | KUKA KRL | GRL |
|
||
| --- | --- | --- | --- | --- |
|
||
| 程序模块 | `MODULE` | TP 程序、KAREL 程序 | `.src/.dat`、`DEF` | `module` |
|
||
| 子程序 | `PROC` | `CALL` | `DEF` 子程序 | `proc` |
|
||
| 函数 | `FUNC` | KAREL function | `DEFFCT` | `func` |
|
||
| 中断/陷阱 | `TRAP`、interrupt | 条件监控、后台逻辑 | `INTERRUPT` | `trap`、`interrupt` |
|
||
| 关节运动 | `MoveJ` | `J P[...]` | `PTP` | `movej` |
|
||
| 直线运动 | `MoveL` | `L P[...]` | `LIN` | `movel` |
|
||
| 圆弧运动 | `MoveC` | `C P[...]` | `CIRC` | `movec` |
|
||
| 笛卡尔目标点 | `robtarget` | `P[]`、`PR[]` | `E6POS` | `pose_target` |
|
||
| 关节目标点 | `jointtarget` | joint position data | `E6AXIS` | `joint_target` |
|
||
| 工具 | `tooldata` | UTOOL | `$TOOL` | `tool` |
|
||
| 工件/基坐标 | `wobjdata` | UFRAME | `$BASE` | `frame` |
|
||
| 速度 | `speeddata` | `%`、`mm/sec` | `$VEL`、`$ACC` | `speed` |
|
||
| 过渡 | `zonedata`、`fine` | `FINE`、`CNT` | `C_DIS`、`C_PTP`、`APO` | `zone` |
|
||
| IO | `SetDO`、`WaitDI` | `DO[]`、`DI[]`、`WAIT` | `$OUT[]`、`$IN[]`、`WAIT FOR` | `io.*`、`wait` |
|
||
| 标签跳转 | `GOTO` | `LBL`、`JMP` | `GOTO` | `label`、`jump` |
|
||
|
||
### 2.2 中性语法风格
|
||
|
||
GRL 采用“声明式数据 + 结构化程序 + Path/Operation 对象”的风格:
|
||
|
||
1. 目标点、工具、坐标系、速度、过渡作为数据声明。
|
||
2. 程序流程使用 `proc`、`if`、`while`、`for`、`switch` 等结构化控制。
|
||
3. 短程序和调试程序可直接写 `movej/movel/movec`。
|
||
4. 自动离线编程优先生成 `path` 和 `operation`,程序中通过 `run_path`、`run_operation` 调用。
|
||
5. 所有运动语句显式绑定目标点、速度、过渡、工具、坐标系,允许默认值,但编译到 IR 前必须解析为确定值。
|
||
6. 品牌特性通过 `post_hint` 和 `@brand.*` 元数据保留,不污染通用语义。
|
||
|
||
## 3. 文件与工程结构
|
||
|
||
推荐一个 OLP 项目使用以下结构:
|
||
|
||
```text
|
||
project.json
|
||
robots/
|
||
robot_1.urdf
|
||
robot_1.meta.json
|
||
programs/
|
||
main.grl
|
||
weld.grl
|
||
targets/
|
||
main.targets.json
|
||
paths/
|
||
weld_path.path.json
|
||
operations/
|
||
weld_op.operation.json
|
||
io/
|
||
io_map.json
|
||
post/
|
||
abb.profile.json
|
||
fanuc.profile.json
|
||
kuka.profile.json
|
||
generated/
|
||
abb/
|
||
fanuc/
|
||
kuka/
|
||
reports/
|
||
reachability.json
|
||
cycle_time.json
|
||
```
|
||
|
||
GRL 文件扩展名建议使用 `.grl`。
|
||
|
||
## 4. 词法规则
|
||
|
||
### 4.1 编码和大小写
|
||
|
||
1. 文件编码使用 UTF-8。
|
||
2. 关键字建议小写。
|
||
3. 标识符大小写敏感,推荐使用 `snake_case`。
|
||
4. 后处理器输出到品牌程序时按品牌习惯调整大小写。
|
||
|
||
### 4.2 注释
|
||
|
||
```text
|
||
// 单行注释
|
||
|
||
/*
|
||
多行注释
|
||
*/
|
||
```
|
||
|
||
自动生成程序应在关键对象上保留来源注释,但不要为每个采样点生成大量冗余注释。
|
||
|
||
### 4.3 标识符
|
||
|
||
```text
|
||
identifier = letter { letter | digit | "_" }
|
||
```
|
||
|
||
示例:
|
||
|
||
```text
|
||
pick_path
|
||
weld_op_01
|
||
T_curve_032_000
|
||
```
|
||
|
||
不建议使用中文标识符。UI 可显示中文别名,但程序内部名称应保持 ASCII,便于后处理和版本管理。
|
||
|
||
### 4.4 字面量和单位
|
||
|
||
支持带单位数值:
|
||
|
||
```text
|
||
100 mm
|
||
0.25 m
|
||
180 deg
|
||
3.14159 rad
|
||
300 mm/s
|
||
50 %
|
||
2 s
|
||
200 ms
|
||
2.5 kg
|
||
```
|
||
|
||
编译器内部统一规范化:
|
||
|
||
| 物理量 | 内部单位 |
|
||
| --- | --- |
|
||
| 长度 | meter |
|
||
| 角度 | radian |
|
||
| 时间 | second |
|
||
| 质量 | kilogram |
|
||
| 线速度 | meter/second |
|
||
| 角速度 | radian/second |
|
||
| 加速度 | meter/second^2 或 radian/second^2 |
|
||
|
||
### 4.5 保留关键字
|
||
|
||
```text
|
||
language module import end
|
||
persistent const var
|
||
robot tool frame load target speed zone path operation process
|
||
proc func return call
|
||
if elseif else switch case default while for to step break continue
|
||
label jump
|
||
movej movel movec run_path run_operation
|
||
set_tool set_frame set_speed set_zone
|
||
wait pulse timer
|
||
io true false all any rising falling changed
|
||
trap interrupt enable disable raise alarm try catch finally
|
||
task sync
|
||
post_hint source defaults point event before after at
|
||
joint_target pose_target pose poseq joints robot_config ext_axis
|
||
fine continuous cnt z
|
||
```
|
||
|
||
## 5. 顶层结构
|
||
|
||
### 5.1 最小文件
|
||
|
||
```text
|
||
language grl 0.1
|
||
|
||
module Main
|
||
proc main()
|
||
// program entry
|
||
end
|
||
end
|
||
```
|
||
|
||
`language grl 0.1` 用于版本控制。后续语言升级时,编译器可按版本选择兼容规则。
|
||
|
||
### 5.2 顶层声明
|
||
|
||
```text
|
||
module ModuleName
|
||
import CommonTools
|
||
|
||
persistent tool gripper = ...
|
||
persistent frame fixture = ...
|
||
const speed v_pick = linear(300 mm/s)
|
||
const zone z_pick = z10
|
||
|
||
target home = ...
|
||
path pick_path { ... }
|
||
operation pick_op { ... }
|
||
|
||
proc main()
|
||
...
|
||
end
|
||
end
|
||
```
|
||
|
||
顶层可包含:
|
||
|
||
1. `import`
|
||
2. `persistent`
|
||
3. `const`
|
||
4. `target`
|
||
5. `path`
|
||
6. `operation`
|
||
7. `proc`
|
||
8. `func`
|
||
9. `trap`
|
||
10. `task`
|
||
11. `post_hint`
|
||
|
||
## 6. 类型系统
|
||
|
||
### 6.1 基础类型
|
||
|
||
| 类型 | 说明 |
|
||
| --- | --- |
|
||
| `bool` | 布尔值 |
|
||
| `int` | 整数 |
|
||
| `real` | 浮点数 |
|
||
| `string` | 字符串 |
|
||
| `time` | 时间 |
|
||
| `length` | 长度 |
|
||
| `angle` | 角度 |
|
||
| `percent` | 百分比 |
|
||
|
||
### 6.2 机器人类型
|
||
|
||
| 类型 | 说明 |
|
||
| --- | --- |
|
||
| `pose` | 笛卡尔位姿 |
|
||
| `joint_array` | 关节数组 |
|
||
| `pose_target` | 笛卡尔目标点 |
|
||
| `joint_target` | 关节目标点 |
|
||
| `tool` | 工具 TCP、负载、惯量 |
|
||
| `frame` | 工件坐标或基坐标 |
|
||
| `speed` | 运动速度参数 |
|
||
| `zone` | 到点/过渡参数 |
|
||
| `load` | 负载 |
|
||
| `robot_config` | 肩、肘、腕等机器人配置 |
|
||
| `ext_axis` | 外部轴 |
|
||
| `path` | 路径对象 |
|
||
| `operation` | 工艺操作对象 |
|
||
|
||
### 6.3 变量声明
|
||
|
||
```text
|
||
const int max_retry = 3
|
||
var int retry = 0
|
||
var bool part_ok = false
|
||
var pose_target p_tmp = pick offset z 100 mm
|
||
persistent real counter = 0
|
||
```
|
||
|
||
规则:
|
||
|
||
1. `const` 编译后不可修改。
|
||
2. `persistent` 在项目或控制器状态中持久化。
|
||
3. `var` 默认为局部变量。
|
||
4. 类型可以显式写出,自动生成程序建议显式写出。
|
||
|
||
## 7. 坐标、工具和目标点
|
||
|
||
### 7.1 工具
|
||
|
||
```text
|
||
persistent tool gripper = tool {
|
||
tcp: pose(0 mm, 0 mm, 180 mm, 0 deg, 0 deg, 0 deg),
|
||
mass: 2.5 kg,
|
||
cog: [0 mm, 0 mm, 80 mm]
|
||
}
|
||
```
|
||
|
||
### 7.2 工件坐标
|
||
|
||
```text
|
||
persistent frame fixture = frame {
|
||
origin: pose(800 mm, 0 mm, 200 mm, 0 deg, 0 deg, 0 deg)
|
||
}
|
||
```
|
||
|
||
### 7.3 关节目标点
|
||
|
||
```text
|
||
target home = joint_target {
|
||
joints: [0 deg, -30 deg, 60 deg, 0 deg, 60 deg, 0 deg]
|
||
}
|
||
```
|
||
|
||
`joint_target` 主要用于 `movej`,后处理可映射到 ABB `jointtarget`、KUKA `E6AXIS` 或 FANUC 关节位置数据。
|
||
|
||
### 7.4 笛卡尔目标点
|
||
|
||
```text
|
||
target pick = pose_target {
|
||
pose: pose(500 mm, 120 mm, 300 mm, 180 deg, 0 deg, 90 deg),
|
||
config: robot_config(0, 0, 1),
|
||
tool: gripper,
|
||
frame: fixture
|
||
}
|
||
```
|
||
|
||
`pose()` 参数顺序为:
|
||
|
||
```text
|
||
pose(x, y, z, rx, ry, rz)
|
||
```
|
||
|
||
首版 `rx/ry/rz` 使用固定约定的欧拉角,建议内部立即转换为四元数。为了避免姿态歧义,也允许使用四元数:
|
||
|
||
```text
|
||
poseq(500 mm, 120 mm, 300 mm, 0, 0, 0.7071068, 0.7071068)
|
||
```
|
||
|
||
### 7.5 偏移目标点
|
||
|
||
```text
|
||
var pose_target approach = pick offset z 100 mm
|
||
var pose_target p2 = pick offset x 20 mm y -10 mm z 50 mm
|
||
```
|
||
|
||
偏移默认在目标点所属 `frame` 下解释。需要明确坐标系时:
|
||
|
||
```text
|
||
var pose_target p3 = pick offset_in tool z -50 mm
|
||
var pose_target p4 = pick offset_in frame fixture x 100 mm
|
||
```
|
||
|
||
## 8. 速度和过渡
|
||
|
||
### 8.1 速度
|
||
|
||
```text
|
||
const speed v_joint_fast = joint(80 %)
|
||
const speed v_joint_abs = joint(90 deg/s)
|
||
const speed v_pick = linear(300 mm/s)
|
||
const speed v_weld = linear(120 mm/s)
|
||
const speed v_orient = angular(90 deg/s)
|
||
```
|
||
|
||
运动语义:
|
||
|
||
1. `joint(...)` 用于关节运动速度。
|
||
2. `linear(...)` 用于 TCP 线速度。
|
||
3. `angular(...)` 可作为姿态插补角速度限制。
|
||
4. 加速度可作为可选参数:
|
||
|
||
```text
|
||
const speed v_slow = linear(100 mm/s, acc 500 mm/s2)
|
||
```
|
||
|
||
### 8.2 过渡
|
||
|
||
```text
|
||
const zone z_fine = fine
|
||
const zone z10 = z(10 mm)
|
||
const zone z50 = z(50 mm)
|
||
const zone z_cnt = cnt(30)
|
||
const zone z_cont = continuous
|
||
```
|
||
|
||
语义:
|
||
|
||
1. `fine`:精确到点,不做过渡。
|
||
2. `z(distance)`:以距离近似表示过渡半径,便于映射 ABB `zonedata` 和 KUKA `APO`。
|
||
3. `cnt(percent)`:以百分比表示连续过渡,便于映射 FANUC `CNT`。
|
||
4. `continuous`:允许连续通过,实际过渡由后处理器或虚拟控制器策略决定。
|
||
|
||
## 9. 运动指令
|
||
|
||
### 9.1 基本语法
|
||
|
||
```text
|
||
movej TargetExpr [speed Speed] [zone Zone] [tool Tool] [frame Frame]
|
||
movel TargetExpr [speed Speed] [zone Zone] [tool Tool] [frame Frame]
|
||
movec via ViaTargetExpr target EndTargetExpr [speed Speed] [zone Zone] [tool Tool] [frame Frame]
|
||
```
|
||
|
||
示例:
|
||
|
||
```text
|
||
movej home speed joint(60 %) zone fine tool gripper frame fixture
|
||
movel pick speed linear(300 mm/s) zone z10
|
||
movec via arc_mid target arc_end speed linear(150 mm/s) zone fine
|
||
```
|
||
|
||
### 9.2 MOVEJ 语义
|
||
|
||
`movej` 表示关节空间运动。机器人按各轴关节角度差分运行,关节同起同停,TCP 轨迹不要求是直线。
|
||
|
||
编译规则:
|
||
|
||
1. 目标为 `joint_target` 时直接使用关节数组。
|
||
2. 目标为 `pose_target` 时先用 IK 求终点关节。
|
||
3. 轨迹按关节空间插补。
|
||
4. 后处理映射:
|
||
- ABB:`MoveJ`
|
||
- FANUC:`J P[...]`
|
||
- KUKA:`PTP`
|
||
|
||
### 9.3 MOVEL 语义
|
||
|
||
`movel` 表示 TCP 直线运动。TCP 沿起点到终点的空间直线运行,关节角由每个 TCP 采样点 IK 求解。
|
||
|
||
编译规则:
|
||
|
||
1. 目标必须能解析为笛卡尔位姿。
|
||
2. 当前点作为直线起点。
|
||
3. 姿态按默认策略插补,首版推荐固定姿态或 slerp。
|
||
4. 后处理映射:
|
||
- ABB:`MoveL`
|
||
- FANUC:`L P[...]`
|
||
- KUKA:`LIN`
|
||
|
||
### 9.4 MOVEC 语义
|
||
|
||
`movec` 表示 TCP 圆弧运动。TCP 从当前点出发,经过 via 点,到达 target 点,沿圆弧运行,关节角由每个圆弧采样点 IK 求解。
|
||
|
||
编译规则:
|
||
|
||
1. 起点为当前 TCP。
|
||
2. `via` 和 `target` 必须能解析为笛卡尔位姿。
|
||
3. 三点不能重合或近似共线。
|
||
4. 首版使用 via 点位置约束圆弧,姿态按起点到终点插补。
|
||
5. 后处理映射:
|
||
- ABB:`MoveC`
|
||
- FANUC:`C P[...]`
|
||
- KUKA:`CIRC`
|
||
|
||
### 9.5 当前工具和当前坐标
|
||
|
||
```text
|
||
set_tool gripper
|
||
set_frame fixture
|
||
set_speed linear(300 mm/s)
|
||
set_zone z10
|
||
```
|
||
|
||
参数优先级:
|
||
|
||
1. 运动语句显式参数最高。
|
||
2. `path defaults` 次之。
|
||
3. 目标点自带 `tool/frame` 次之。
|
||
4. 当前控制器状态最低。
|
||
|
||
编译到 IR 时,所有运动必须有确定的 `tool`、`frame`、`speed`、`zone`。
|
||
|
||
## 10. Path 语法
|
||
|
||
Path 是自动离线编程的核心对象。CAD 曲线、规划点、示教点、工艺模板应优先生成 Path,而不是直接生成散乱运动语句。
|
||
|
||
### 10.1 基本语法
|
||
|
||
```text
|
||
path pick_path {
|
||
defaults {
|
||
tool: gripper,
|
||
frame: fixture,
|
||
speed: linear(300 mm/s),
|
||
zone: z10
|
||
}
|
||
|
||
point approach movej home zone fine
|
||
point p1 movel pick offset z 100 mm
|
||
point p2 movel pick zone fine
|
||
}
|
||
```
|
||
|
||
### 10.2 圆弧点
|
||
|
||
```text
|
||
path arc_path {
|
||
defaults {
|
||
tool: torch,
|
||
frame: part_frame,
|
||
speed: linear(120 mm/s),
|
||
zone: fine
|
||
}
|
||
|
||
point p0 movej start
|
||
point p1 movec via mid target end
|
||
}
|
||
```
|
||
|
||
### 10.3 来源元数据
|
||
|
||
```text
|
||
path curve_032_generated {
|
||
source {
|
||
type: cad_curve
|
||
id: "edge_032"
|
||
sample_distance: 5 mm
|
||
normal_strategy: surface_normal
|
||
}
|
||
|
||
defaults {
|
||
tool: spray_gun,
|
||
frame: part_frame,
|
||
speed: linear(500 mm/s),
|
||
zone: z20,
|
||
posture: follow_normal
|
||
}
|
||
|
||
point p000 movel T_curve_032_000 zone fine
|
||
point p001 movel T_curve_032_001
|
||
point p002 movel T_curve_032_002
|
||
}
|
||
```
|
||
|
||
来源元数据用于:
|
||
|
||
1. 路径重采样。
|
||
2. 目标点重命名。
|
||
3. 重新生成程序。
|
||
4. 报告中定位到 CAD 曲线或工艺对象。
|
||
|
||
### 10.4 Path event
|
||
|
||
```text
|
||
event before p001 io.do[10] = true
|
||
event after p010 io.do[10] = false
|
||
event at p005 distance -20 mm pulse io.do[20] duration 100 ms
|
||
```
|
||
|
||
语义:
|
||
|
||
1. `before`:到达路径点之前执行。
|
||
2. `after`:完成路径点之后执行。
|
||
3. `at ... distance`:相对路径点提前或滞后触发,首版可编译为最近采样点事件。
|
||
4. 后处理到品牌程序时,若品牌不支持精确路径触发,应生成转换报告。
|
||
|
||
### 10.5 `run_path`
|
||
|
||
```text
|
||
proc main()
|
||
run_path pick_path
|
||
end
|
||
```
|
||
|
||
编译语义:
|
||
|
||
1. 展开 Path 的 defaults、points、events。
|
||
2. 每个 point 变为 Motion IR。
|
||
3. event 变为 IO/Wait/Process IR。
|
||
4. 保留 source map,调试时可从程序行定位到路径点。
|
||
|
||
## 11. Operation 语法
|
||
|
||
Operation 表达工艺语义,比 Path 更高一层。
|
||
|
||
```text
|
||
operation weld_op_01 {
|
||
kind: arc_welding
|
||
path: weld_seam_01
|
||
|
||
process {
|
||
weld_id: "WELD_1"
|
||
voltage: 24.0
|
||
current: 180.0
|
||
weave: none
|
||
}
|
||
|
||
start_action:
|
||
io.do[20] = true
|
||
|
||
end_action:
|
||
io.do[20] = false
|
||
}
|
||
```
|
||
|
||
首版建议支持的 `kind`:
|
||
|
||
| kind | 用途 |
|
||
| --- | --- |
|
||
| `handling` | 搬运、上下料 |
|
||
| `arc_welding` | 弧焊 |
|
||
| `spot_welding` | 点焊 |
|
||
| `dispensing` | 涂胶 |
|
||
| `spraying` | 喷涂 |
|
||
| `grinding` | 打磨 |
|
||
| `cutting` | 切割 |
|
||
| `generic_path` | 通用路径 |
|
||
|
||
`run_operation`:
|
||
|
||
```text
|
||
proc main()
|
||
run_operation weld_op_01
|
||
end
|
||
```
|
||
|
||
编译语义:
|
||
|
||
1. 执行 `start_action`。
|
||
2. 执行 operation 引用的 path。
|
||
3. 执行 `end_action`。
|
||
4. 保留工艺参数,供仿真 UI、报告和后处理使用。
|
||
|
||
## 12. IO 与等待
|
||
|
||
### 12.1 IO 地址
|
||
|
||
```text
|
||
io.di[1]
|
||
io.do[1]
|
||
io.ai[1]
|
||
io.ao[1]
|
||
io.gi[1]
|
||
io.go[1]
|
||
io.ri[1]
|
||
io.ro[1]
|
||
```
|
||
|
||
推荐通过 `io_map.json` 提供别名:
|
||
|
||
```text
|
||
io.alias.clamp_open
|
||
io.alias.clamp_closed
|
||
io.alias.gripper_close_cmd
|
||
```
|
||
|
||
### 12.2 IO 写入
|
||
|
||
```text
|
||
io.do[1] = true
|
||
io.go[1] = 16
|
||
io.ao[1] = 3.5
|
||
```
|
||
|
||
### 12.3 wait
|
||
|
||
```text
|
||
wait io.di[1] == true
|
||
wait io.alias.clamp_closed == true timeout 2 s
|
||
wait io.ai[2] > 3.5 timeout 1.5 s
|
||
wait all(io.di[1] == true, io.di[2] == false)
|
||
wait any(io.di[10] == true, timer.done("T_PICK"))
|
||
wait rising(io.di[4]) timeout 5 s
|
||
wait falling(io.di[5]) timeout 5 s
|
||
```
|
||
|
||
超时处理:
|
||
|
||
```text
|
||
wait io.di[1] == true timeout 2 s on_timeout alarm "Clamp close timeout"
|
||
wait io.di[1] == true timeout 2 s on_timeout call recover_clamp()
|
||
```
|
||
|
||
### 12.4 pulse
|
||
|
||
```text
|
||
pulse io.do[3] duration 200 ms
|
||
```
|
||
|
||
虚拟控制器语义:
|
||
|
||
1. 立即置位输出。
|
||
2. 虚拟时间到达 duration 后自动复位。
|
||
3. trace 中必须记录置位和复位事件。
|
||
|
||
## 13. 流程控制
|
||
|
||
流程控制用于表达工艺分支、重试、配方选择、批量工位循环和异常恢复。GRL 新程序应优先使用结构化控制流;`label/jump` 主要用于兼容 FANUC TP/LS 等已有程序导入。
|
||
|
||
### 13.1 条件 `if / elseif / else`
|
||
|
||
```text
|
||
if part_ok
|
||
run_path good_path
|
||
elseif retry < 3
|
||
call retry_pick()
|
||
else
|
||
alarm "Pick failed"
|
||
end
|
||
```
|
||
|
||
语义规则:
|
||
|
||
1. `if` 条件表达式必须能转换为 `bool`。
|
||
2. `elseif` 可以出现零次或多次。
|
||
3. `else` 最多出现一次,且必须位于所有 `elseif` 之后。
|
||
4. 条件按顺序求值,命中第一条为 true 的分支后,不再执行后续分支。
|
||
5. 每个 `if` 必须以 `end` 结束。
|
||
6. 条件表达式允许访问变量、IO、函数返回值和比较表达式。
|
||
7. 运动指令允许出现在任意分支内,但编译器必须保证每条分支中的工具、坐标系、速度和 zone 可解析。
|
||
|
||
常用条件表达式:
|
||
|
||
```text
|
||
if io.di[1] == true
|
||
if count >= 3 and not part_ok
|
||
if is_part_ready()
|
||
if recipe_id == 2 or recipe_id == 3
|
||
```
|
||
|
||
### 13.2 `while` 循环
|
||
|
||
```text
|
||
while retry < 3
|
||
call try_pick()
|
||
if part_ok
|
||
break
|
||
end
|
||
retry = retry + 1
|
||
end
|
||
```
|
||
|
||
语义规则:
|
||
|
||
1. `while` 条件必须为 `bool`。
|
||
2. 每次进入循环前求值。
|
||
3. `break` 立即退出当前循环。
|
||
4. `continue` 跳过本轮剩余语句,进入下一轮条件判断。
|
||
5. 编译器建议对可能无限循环的 `while true` 给出 warning,除非循环体内包含明确的 `break`、`return`、`raise` 或 `wait`。
|
||
|
||
### 13.3 `for` 循环
|
||
|
||
```text
|
||
for i = 0 to 9 step 1
|
||
call process_slot(i)
|
||
end
|
||
```
|
||
|
||
也允许省略 `step`,默认步长为 `1`:
|
||
|
||
```text
|
||
for layer = 1 to layer_count
|
||
call weld_layer(layer)
|
||
end
|
||
```
|
||
|
||
反向循环:
|
||
|
||
```text
|
||
for i = 10 to 0 step -1
|
||
call clear_slot(i)
|
||
end
|
||
```
|
||
|
||
语义规则:
|
||
|
||
1. 循环变量默认是当前 `for` 块局部变量。
|
||
2. 起点、终点、步长必须是整数或可安全转换为整数。
|
||
3. `step` 不能为 `0`。
|
||
4. `break` 和 `continue` 只影响当前最近一层循环。
|
||
5. 后处理到不支持结构化 `for` 的品牌时,可展开为标签和跳转,但必须保持 source map。
|
||
|
||
### 13.4 `switch / case / default`
|
||
|
||
```text
|
||
switch recipe_id
|
||
case 1
|
||
run_operation op_a
|
||
case 2
|
||
run_operation op_b
|
||
default
|
||
alarm "Unknown recipe"
|
||
end
|
||
```
|
||
|
||
语义规则:
|
||
|
||
1. `switch` 表达式可以是 `int`、`bool`、`string` 或枚举型。
|
||
2. `case` 值必须是常量表达式。
|
||
3. 每个 `case` 默认不向下贯穿,不需要写 `break`。
|
||
4. `default` 最多出现一次。
|
||
5. 若需要多个值进入同一分支,可以使用逗号:
|
||
|
||
```text
|
||
switch recipe_id
|
||
case 1, 2, 3
|
||
run_operation common_recipe
|
||
case 10
|
||
run_operation special_recipe
|
||
default
|
||
alarm "Unknown recipe"
|
||
end
|
||
```
|
||
|
||
6. 导出到 FANUC TP/LS 时,`switch` 可转换为 `SELECT`、条件跳转或 `LBL/JMP` 组合。
|
||
7. 导出到 ABB/KUKA 时,优先转换为品牌结构化分支。
|
||
|
||
### 13.5 `break` 和 `continue`
|
||
|
||
```text
|
||
while true
|
||
call check_part()
|
||
if part_ok
|
||
break
|
||
end
|
||
retry = retry + 1
|
||
if retry < max_retry
|
||
continue
|
||
end
|
||
alarm "Retry failed"
|
||
break
|
||
end
|
||
```
|
||
|
||
规则:
|
||
|
||
1. `break` 只能出现在 `while`、`for` 或 `switch` 中。
|
||
2. `continue` 只能出现在 `while` 或 `for` 中。
|
||
3. 在 `switch` 中不需要 `break` 防止贯穿,因为 GRL 默认不贯穿。
|
||
|
||
### 13.6 label 和 jump
|
||
|
||
```text
|
||
label retry
|
||
call try_pick()
|
||
if not part_ok
|
||
jump retry
|
||
end
|
||
```
|
||
|
||
新程序不建议优先使用 `label/jump`,但必须支持它,因为 FANUC TP/LS 程序常用 `LBL/JMP`,导入时需要映射。
|
||
|
||
`label/jump` 规则:
|
||
|
||
1. `label` 名称在当前 `proc` 内唯一。
|
||
2. `jump` 只能跳转到当前 `proc` 内的 label。
|
||
3. 禁止 `jump` 进入另一个 `if/while/for/switch/try` 块内部。
|
||
4. 允许 `jump` 跳出块结构,但编译器应生成 warning。
|
||
5. 自动生成的新程序不应使用 `label/jump`,除非目标后处理配置要求 FANUC 风格输出。
|
||
|
||
## 14. 子程序和函数
|
||
|
||
### 14.1 `proc` 子程序
|
||
|
||
`proc` 是无返回值子程序,用于组织工艺步骤、运动流程、IO 流程和恢复逻辑。
|
||
|
||
```text
|
||
proc pick_part(int slot)
|
||
movej home speed joint(60 %) zone fine
|
||
run_path pick_path
|
||
end
|
||
```
|
||
|
||
调用:
|
||
|
||
```text
|
||
call pick_part(1)
|
||
call pick_part(slot_id)
|
||
```
|
||
|
||
语义规则:
|
||
|
||
1. `proc` 可以执行运动、IO、wait、run_path、run_operation。
|
||
2. `proc` 可以调用其他 `proc`。
|
||
3. 默认不允许无限递归。编译器应检测直接递归和明显的间接递归,并给出 warning 或 error。
|
||
4. `return` 可以提前退出 `proc`,但不能携带返回值。
|
||
5. `proc main()` 是默认入口。一个模块中最多一个默认入口。
|
||
|
||
### 14.2 参数方向
|
||
|
||
参数支持 `in`、`out`、`inout` 三种方向。未写方向时默认为 `in`。
|
||
|
||
```text
|
||
proc pick_part(in int slot)
|
||
call move_to_slot(slot)
|
||
end
|
||
|
||
proc read_part(out bool ok)
|
||
ok = io.di[1]
|
||
end
|
||
|
||
proc increment_retry(inout int retry)
|
||
retry = retry + 1
|
||
end
|
||
```
|
||
|
||
规则:
|
||
|
||
1. `in` 参数按值传入,子程序内修改不影响调用者。
|
||
2. `out` 参数调用前不要求有有效值,子程序必须在所有正常返回路径上赋值。
|
||
3. `inout` 参数按引用语义传入,子程序内修改会回写调用者。
|
||
4. `out` 和 `inout` 实参必须是可赋值左值,不能是字面量或表达式。
|
||
5. 后处理到不支持显式参数方向的品牌时,可生成临时变量、寄存器或转换报告。
|
||
|
||
调用示例:
|
||
|
||
```text
|
||
var bool ok = false
|
||
var int retry = 0
|
||
|
||
call read_part(ok)
|
||
call increment_retry(retry)
|
||
```
|
||
|
||
### 14.3 `func` 函数
|
||
|
||
`func` 有返回值,适合计算条件、选择目标点、计算偏移、读取配方参数。函数应尽量无副作用。
|
||
|
||
```text
|
||
func bool is_part_ready()
|
||
return io.di[1] == true and io.di[2] == false
|
||
end
|
||
```
|
||
|
||
带参数函数:
|
||
|
||
```text
|
||
func pose_target slot_pose(int slot)
|
||
return base_pick offset x (slot * 50 mm)
|
||
end
|
||
|
||
func bool can_retry(int retry, int max_retry)
|
||
return retry < max_retry
|
||
end
|
||
```
|
||
|
||
调用方式:
|
||
|
||
```text
|
||
if can_retry(retry, max_retry)
|
||
call retry_pick()
|
||
end
|
||
|
||
movel slot_pose(slot_id) speed linear(200 mm/s) zone z10
|
||
```
|
||
|
||
规则:
|
||
|
||
1. `func` 必须声明返回类型。
|
||
2. 所有正常返回路径必须返回兼容类型的值。
|
||
3. `func` 允许调用其他 `func`。
|
||
4. `func` 默认不允许执行运动指令、`wait`、`pulse`、`run_path`、`run_operation`。编译器应把这类用法作为 error 或强 warning。
|
||
5. 如果确实需要带副作用的逻辑,应使用 `proc`。
|
||
|
||
### 14.4 作用域和名称解析
|
||
|
||
名称解析顺序:
|
||
|
||
1. 当前块局部变量。
|
||
2. 当前 `proc/func` 参数。
|
||
3. 当前模块中的 `const/var/persistent/target/path/operation/proc/func`。
|
||
4. `import` 模块导出的符号。
|
||
5. 内置函数和内置类型。
|
||
|
||
规则:
|
||
|
||
1. 内层局部变量允许遮蔽外层变量,但编译器应对同名遮蔽给出 warning。
|
||
2. 不允许局部变量与同一作用域内的 `proc/func/target/path/operation` 重名。
|
||
3. `for` 循环变量只在循环体内有效。
|
||
4. `label` 只在当前 `proc` 内有效。
|
||
|
||
### 14.5 子程序调用和后处理
|
||
|
||
后处理映射:
|
||
|
||
| GRL | ABB RAPID | FANUC LS/TP | KUKA KRL |
|
||
| --- | --- | --- | --- |
|
||
| `proc name()` | `PROC name()` | `/PROG NAME` 或子程序 | `DEF name()` |
|
||
| `call sub()` | `sub;` 或 `sub()` | `CALL SUB` | `sub()` |
|
||
| `return` | `RETURN` | `END`/跳转近似 | `RETURN` |
|
||
| `out/inout` 参数 | `VAR` 参数或数据变量 | 寄存器/PR/临时变量近似 | 参数或全局变量近似 |
|
||
|
||
如果目标品牌或输出格式不支持某种参数模式,后处理器必须生成转换报告,不能静默丢失语义。
|
||
|
||
## 15. 异常、报警和中断
|
||
|
||
### 15.1 alarm 和 raise
|
||
|
||
```text
|
||
alarm "Part not detected"
|
||
raise E_PICK_FAILED
|
||
```
|
||
|
||
### 15.2 try/catch
|
||
|
||
```text
|
||
try
|
||
run_operation pick_op
|
||
catch E_PICK_FAILED
|
||
call recover_pick()
|
||
finally
|
||
io.do[1] = false
|
||
end
|
||
```
|
||
|
||
首版可先实现 `alarm`、`raise` 和简单 `catch`,复杂品牌错误恢复分阶段支持。
|
||
|
||
### 15.3 trap 和 interrupt
|
||
|
||
```text
|
||
trap emergency_stop()
|
||
stop_motion
|
||
io.do[100] = false
|
||
alarm "Emergency stop input"
|
||
end
|
||
|
||
interrupt e_stop when io.di[100] == true call emergency_stop()
|
||
enable interrupt e_stop
|
||
disable interrupt e_stop
|
||
```
|
||
|
||
后处理映射:
|
||
|
||
1. ABB 可映射到 `TRAP` 和 interrupt 机制。
|
||
2. KUKA 可映射到 `INTERRUPT DECL`、`INTERRUPT ON/OFF` 等近似结构。
|
||
3. FANUC 首版可生成后台逻辑、条件监控或转换报告。
|
||
|
||
## 16. 多任务
|
||
|
||
首版只定义语法,不要求完整实现多任务实时调度:
|
||
|
||
```text
|
||
task background monitor_io cycle 20 ms
|
||
if io.di[99] == true
|
||
alarm "Safety signal lost"
|
||
end
|
||
end
|
||
```
|
||
|
||
虚拟控制器可先按周期任务模拟;后处理时根据品牌能力生成后台任务或转换报告。
|
||
|
||
## 17. 品牌扩展和后处理提示
|
||
|
||
### 17.1 post_hint
|
||
|
||
```text
|
||
post_hint abb {
|
||
module_name: "MainModule"
|
||
use_wobj: true
|
||
}
|
||
|
||
post_hint fanuc {
|
||
program_name: "MAIN"
|
||
default_uframe: 1
|
||
default_utool: 1
|
||
}
|
||
|
||
post_hint kuka {
|
||
src_name: "MAIN"
|
||
dat_name: "MAIN"
|
||
advance: 3
|
||
}
|
||
```
|
||
|
||
### 17.2 brand metadata
|
||
|
||
```text
|
||
@brand.abb {
|
||
conf_l: true
|
||
}
|
||
|
||
@brand.fanuc {
|
||
group: 1
|
||
cnt: 50
|
||
}
|
||
|
||
@brand.kuka {
|
||
c_dis: true
|
||
}
|
||
```
|
||
|
||
规则:
|
||
|
||
1. `@brand.*` 只影响指定品牌后处理。
|
||
2. 通用虚拟控制器不应依赖品牌 metadata 才能执行。
|
||
3. 无法支持的品牌扩展必须进入转换报告。
|
||
|
||
## 18. 自动编程生成规则
|
||
|
||
自动生成 GRL 时,应遵循以下规则:
|
||
|
||
1. 优先生成 `target`、`path`、`operation`,不要直接把大量运动语句塞进 `proc main()`。
|
||
2. 目标点命名稳定,推荐 `T_{path}_{index}` 或语义名称,例如 `T_PICK_APPROACH`。
|
||
3. 路径点命名稳定,推荐 `p000`、`p001`、`p002`。
|
||
4. 路径整体参数放入 `defaults`,单点差异写在 point 上。
|
||
5. 接近点、工艺开始点、工艺结束点、离开点必须显式标注。
|
||
6. IO、夹具、焊接开关、喷涂开关应生成 path event 或 operation action。
|
||
7. CAD 来源、曲线 ID、采样距离、法向策略必须写入 `source`。
|
||
8. 自动生成文本必须格式化稳定,同一输入重复生成结果一致。
|
||
9. 编译器应能把 GRL 再解析回等价 OLP 对象模型。
|
||
10. 后处理器应能选择 `compact` 或 `expanded` 输出风格。
|
||
|
||
生成风格:
|
||
|
||
```text
|
||
// compact
|
||
proc main()
|
||
run_operation weld_op_01
|
||
end
|
||
|
||
// expanded
|
||
proc main()
|
||
movel T001 speed linear(120 mm/s) zone z5 tool torch frame part_frame
|
||
movel T002 speed linear(120 mm/s) zone z5 tool torch frame part_frame
|
||
end
|
||
```
|
||
|
||
## 19. 后处理映射规则
|
||
|
||
### 19.1 ABB RAPID
|
||
|
||
| GRL | ABB RAPID |
|
||
| --- | --- |
|
||
| `module` | `MODULE` |
|
||
| `proc` | `PROC` |
|
||
| `movej` | `MoveJ` |
|
||
| `movel` | `MoveL` |
|
||
| `movec` | `MoveC` |
|
||
| `pose_target` | `robtarget` |
|
||
| `joint_target` | `jointtarget` |
|
||
| `tool` | `tooldata` |
|
||
| `frame` | `wobjdata` |
|
||
| `linear(300 mm/s)` | `v300` 或自定义 `speeddata` |
|
||
| `fine`、`z(10 mm)` | `fine`、`z10` 或自定义 `zonedata` |
|
||
| `io.do[1] = true` | `SetDO do1, 1` |
|
||
| `wait io.di[1] == true` | `WaitDI di1, 1` |
|
||
|
||
示例:
|
||
|
||
```text
|
||
movel pick speed linear(300 mm/s) zone z10 tool gripper frame fixture
|
||
```
|
||
|
||
可后处理为:
|
||
|
||
```text
|
||
MoveL pick, v300, z10, gripper\WObj:=fixture;
|
||
```
|
||
|
||
### 19.2 FANUC LS/TP 风格
|
||
|
||
| GRL | FANUC |
|
||
| --- | --- |
|
||
| `proc main()` | `/PROG MAIN` |
|
||
| `movej` | `J P[...]` |
|
||
| `movel` | `L P[...]` |
|
||
| `movec` | `C P[...]` |
|
||
| `pose_target` | `P[...]` 或 `PR[...]` |
|
||
| `tool` | UTOOL |
|
||
| `frame` | UFRAME |
|
||
| `joint(50 %)` | `50%` |
|
||
| `linear(300 mm/s)` | `300mm/sec` |
|
||
| `fine` | `FINE` |
|
||
| `cnt(50)` | `CNT50` |
|
||
| `io.do[1] = true` | `DO[1]=ON` |
|
||
| `wait io.di[1] == true` | `WAIT DI[1]=ON` |
|
||
|
||
示例:
|
||
|
||
```text
|
||
movel P10 speed linear(300 mm/s) zone cnt(10)
|
||
```
|
||
|
||
可后处理为:
|
||
|
||
```text
|
||
L P[10] 300mm/sec CNT10 ;
|
||
```
|
||
|
||
### 19.3 KUKA KRL
|
||
|
||
| GRL | KUKA KRL |
|
||
| --- | --- |
|
||
| `proc main()` | `DEF MAIN()` |
|
||
| `movej` | `PTP` |
|
||
| `movel` | `LIN` |
|
||
| `movec` | `CIRC` |
|
||
| `pose_target` | `E6POS` |
|
||
| `joint_target` | `E6AXIS` |
|
||
| `tool` | `$TOOL` |
|
||
| `frame` | `$BASE` |
|
||
| `linear(300 mm/s)` | `$VEL.CP = 0.3` |
|
||
| `fine` | no approximation |
|
||
| `continuous`、`z(...)` | `C_DIS` 或 `$APO` |
|
||
| `io.do[1] = true` | `$OUT[1] = TRUE` |
|
||
| `wait io.di[1] == true` | `WAIT FOR $IN[1] == TRUE` |
|
||
|
||
示例:
|
||
|
||
```text
|
||
movel XPICK speed linear(300 mm/s) zone continuous
|
||
```
|
||
|
||
可后处理为:
|
||
|
||
```text
|
||
$VEL.CP = 0.3
|
||
LIN XPICK C_DIS
|
||
```
|
||
|
||
## 20. 编译语义和 IR
|
||
|
||
编译管线:
|
||
|
||
```text
|
||
GRL Source
|
||
-> Lexer
|
||
-> Parser
|
||
-> AST
|
||
-> Symbol Table
|
||
-> Semantic Analyzer
|
||
-> Executable IR
|
||
-> Virtual Controller
|
||
-> Post Processor
|
||
```
|
||
|
||
运动 IR 示例:
|
||
|
||
```ts
|
||
interface MotionInstruction {
|
||
kind: "motion";
|
||
motionType: "joint" | "linear" | "circular";
|
||
target: TargetRef | ResolvedTarget;
|
||
via?: TargetRef | ResolvedTarget;
|
||
speed: SpeedSpec;
|
||
zone: ZoneSpec;
|
||
tool: ToolRef;
|
||
frame: FrameRef;
|
||
sourceRange: SourceRange;
|
||
sourceObject?: {
|
||
pathId?: string;
|
||
pointId?: string;
|
||
operationId?: string;
|
||
};
|
||
brandMeta?: Record<string, unknown>;
|
||
}
|
||
```
|
||
|
||
## 21. 语义检查
|
||
|
||
编译器必须检查:
|
||
|
||
1. 标识符是否重复或未声明。
|
||
2. 类型是否匹配。
|
||
3. 目标点类型是否适合运动指令。
|
||
4. `movec` 是否缺少 via 点。
|
||
5. 圆弧三点是否重合或共线。
|
||
6. 工具、坐标系、速度、过渡是否可解析。
|
||
7. 单位是否正确。
|
||
8. IO 地址是否存在于 IO map 或允许范围。
|
||
9. 子程序参数数量和类型是否匹配。
|
||
10. `out` 参数是否在所有正常返回路径上赋值。
|
||
11. `inout` 和 `out` 实参是否为可赋值左值。
|
||
12. `func` 是否在所有正常返回路径上返回正确类型。
|
||
13. `break`、`continue` 是否出现在合法结构内。
|
||
14. `switch case` 是否为常量表达式,是否存在重复 case。
|
||
15. `jump` 是否跳入非法块结构。
|
||
16. `wait` 是否有可执行条件。
|
||
17. Path 是否为空。
|
||
18. Path point 名称是否重复。
|
||
19. Operation 是否引用不存在的 Path。
|
||
20. 目标点是否可达。
|
||
21. 关节是否超限。
|
||
22. 后处理目标品牌是否支持所用语义。
|
||
|
||
诊断格式建议:
|
||
|
||
```text
|
||
E1001: target 'pick' is not defined
|
||
E2003: movec points are collinear: start=p0, via=p1, target=p2
|
||
W3002: zone z50 is larger than segment length
|
||
W4001: KUKA post approximates GRL cnt(30) by C_DIS
|
||
```
|
||
|
||
## 22. EBNF 语法草案
|
||
|
||
以下是首版解析器可采用的简化 EBNF:
|
||
|
||
```text
|
||
program = [ language_decl ] module_decl ;
|
||
language_decl = "language" "grl" version ;
|
||
module_decl = "module" identifier { top_decl } "end" ;
|
||
|
||
top_decl = import_decl
|
||
| data_decl
|
||
| target_decl
|
||
| path_decl
|
||
| operation_decl
|
||
| proc_decl
|
||
| func_decl
|
||
| trap_decl
|
||
| task_decl
|
||
| post_hint_decl ;
|
||
|
||
import_decl = "import" identifier ;
|
||
data_decl = ( "persistent" | "const" | "var" ) type identifier "=" expr ;
|
||
target_decl = "target" identifier "=" ( joint_target | pose_target ) ;
|
||
|
||
joint_target = "joint_target" "{" "joints" ":" array [ "," ext_axis ] "}" ;
|
||
pose_target = "pose_target" "{" "pose" ":" pose_expr
|
||
[ "," "config" ":" config_expr ]
|
||
[ "," "tool" ":" identifier ]
|
||
[ "," "frame" ":" identifier ] "}" ;
|
||
|
||
path_decl = "path" identifier "{" { path_item } "}" ;
|
||
path_item = defaults_block | source_block | path_point | path_event ;
|
||
defaults_block = "defaults" "{" { property } "}" ;
|
||
source_block = "source" "{" { property } "}" ;
|
||
path_point = "point" identifier motion_stmt ;
|
||
path_event = "event" ( "before" | "after" ) identifier statement ;
|
||
|
||
operation_decl = "operation" identifier "{"
|
||
"kind" ":" identifier
|
||
"path" ":" identifier
|
||
[ process_block ]
|
||
[ action_block ]
|
||
"}" ;
|
||
|
||
proc_decl = "proc" identifier "(" [ param_list ] ")" { statement } "end" ;
|
||
func_decl = "func" type identifier "(" [ param_list ] ")" { statement } "end" ;
|
||
trap_decl = "trap" identifier "(" ")" { statement } "end" ;
|
||
|
||
statement = motion_stmt
|
||
| run_stmt
|
||
| assign_stmt
|
||
| wait_stmt
|
||
| pulse_stmt
|
||
| if_stmt
|
||
| while_stmt
|
||
| for_stmt
|
||
| switch_stmt
|
||
| call_stmt
|
||
| return_stmt
|
||
| break_stmt
|
||
| continue_stmt
|
||
| label_stmt
|
||
| jump_stmt
|
||
| alarm_stmt
|
||
| try_stmt ;
|
||
|
||
motion_stmt = movej_stmt | movel_stmt | movec_stmt ;
|
||
target_expr = target_ref [ offset_clause ] | pose_expr ;
|
||
offset_clause = "offset" { axis length }
|
||
| "offset_in" ( "tool" | "frame" identifier ) { axis length } ;
|
||
movej_stmt = "movej" target_expr motion_params ;
|
||
movel_stmt = "movel" target_expr motion_params ;
|
||
movec_stmt = "movec" "via" target_expr "target" target_expr motion_params ;
|
||
|
||
motion_params = [ "speed" speed_expr ] [ "zone" zone_expr ]
|
||
[ "tool" identifier ] [ "frame" identifier ] ;
|
||
|
||
run_stmt = "run_path" identifier | "run_operation" identifier ;
|
||
wait_stmt = "wait" expr [ "timeout" duration ] [ "on_timeout" timeout_action ] ;
|
||
pulse_stmt = "pulse" io_ref "duration" duration ;
|
||
assign_stmt = lvalue "=" expr ;
|
||
call_stmt = "call" identifier "(" [ arg_list ] ")" ;
|
||
return_stmt = "return" [ expr ] ;
|
||
break_stmt = "break" ;
|
||
continue_stmt = "continue" ;
|
||
|
||
if_stmt = "if" expr { statement }
|
||
{ "elseif" expr { statement } }
|
||
[ "else" { statement } ]
|
||
"end" ;
|
||
|
||
while_stmt = "while" expr { statement } "end" ;
|
||
for_stmt = "for" identifier "=" expr "to" expr [ "step" expr ] { statement } "end" ;
|
||
|
||
switch_stmt = "switch" expr { case_clause } [ default_clause ] "end" ;
|
||
case_clause = "case" const_expr { "," const_expr } { statement } ;
|
||
default_clause = "default" { statement } ;
|
||
|
||
label_stmt = "label" identifier ;
|
||
jump_stmt = "jump" identifier ;
|
||
|
||
param_list = param { "," param } ;
|
||
param = [ "in" | "out" | "inout" ] type identifier ;
|
||
arg_list = expr { "," expr } ;
|
||
|
||
expr = literal
|
||
| identifier
|
||
| call_expr
|
||
| io_ref
|
||
| unary_expr
|
||
| binary_expr
|
||
| "(" expr ")" ;
|
||
call_expr = identifier "(" [ arg_list ] ")" ;
|
||
```
|
||
|
||
## 23. 完整示例
|
||
|
||
```text
|
||
language grl 0.1
|
||
|
||
module Main
|
||
|
||
persistent tool gripper = tool {
|
||
tcp: pose(0 mm, 0 mm, 180 mm, 0 deg, 0 deg, 0 deg),
|
||
mass: 2.5 kg
|
||
}
|
||
|
||
persistent frame fixture = frame {
|
||
origin: pose(800 mm, 0 mm, 200 mm, 0 deg, 0 deg, 0 deg)
|
||
}
|
||
|
||
const speed v_fast = joint(70 %)
|
||
const speed v_pick = linear(300 mm/s)
|
||
const zone z_pick = z(10 mm)
|
||
|
||
target home = joint_target {
|
||
joints: [0 deg, -30 deg, 60 deg, 0 deg, 60 deg, 0 deg]
|
||
}
|
||
|
||
target pick = pose_target {
|
||
pose: pose(500 mm, 120 mm, 300 mm, 180 deg, 0 deg, 90 deg),
|
||
config: robot_config(0, 0, 1),
|
||
tool: gripper,
|
||
frame: fixture
|
||
}
|
||
|
||
target place = pose_target {
|
||
pose: pose(650 mm, -100 mm, 320 mm, 180 deg, 0 deg, 90 deg),
|
||
config: robot_config(0, 0, 1),
|
||
tool: gripper,
|
||
frame: fixture
|
||
}
|
||
|
||
path pick_path {
|
||
defaults {
|
||
tool: gripper,
|
||
frame: fixture,
|
||
speed: v_pick,
|
||
zone: z_pick
|
||
}
|
||
|
||
point approach movej home speed v_fast zone fine
|
||
point above_pick movel pick offset z 100 mm
|
||
point at_pick movel pick zone fine
|
||
event after at_pick io.do[1] = true
|
||
event after at_pick wait io.di[1] == true timeout 2 s on_timeout alarm "Clamp close timeout"
|
||
point leave_pick movel pick offset z 100 mm
|
||
}
|
||
|
||
path place_path {
|
||
defaults {
|
||
tool: gripper,
|
||
frame: fixture,
|
||
speed: v_pick,
|
||
zone: z_pick
|
||
}
|
||
|
||
point above_place movel place offset z 100 mm
|
||
point at_place movel place zone fine
|
||
event after at_place io.do[1] = false
|
||
event after at_place wait io.di[2] == true timeout 2 s on_timeout alarm "Clamp open timeout"
|
||
point leave_place movel place offset z 100 mm
|
||
}
|
||
|
||
operation pick_op {
|
||
kind: handling
|
||
path: pick_path
|
||
process {
|
||
gripper: "main_clamp"
|
||
}
|
||
}
|
||
|
||
operation place_op {
|
||
kind: handling
|
||
path: place_path
|
||
process {
|
||
gripper: "main_clamp"
|
||
}
|
||
}
|
||
|
||
proc main()
|
||
set_tool gripper
|
||
set_frame fixture
|
||
|
||
run_operation pick_op
|
||
run_operation place_op
|
||
|
||
movej home speed v_fast zone fine
|
||
end
|
||
|
||
end
|
||
```
|
||
|
||
## 24. 实施优先级
|
||
|
||
P0 必须实现:
|
||
|
||
1. `language`、`module`、`proc`。
|
||
2. `const`、`var`、`persistent`。
|
||
3. `tool`、`frame`、`speed`、`zone`。
|
||
4. `joint_target`、`pose_target`。
|
||
5. `movej`、`movel`、`movec`。
|
||
6. `path`、`point`、`event`、`run_path`。
|
||
7. `operation`、`run_operation`。
|
||
8. `if`、`elseif`、`else`、`while`、`for`、`switch`。
|
||
9. `call`、`return`、`break`、`continue`。
|
||
10. `proc` 参数方向 `in/out/inout`。
|
||
11. `func`、函数调用表达式和返回值检查。
|
||
12. `io.do/di`、`wait`、`pulse`。
|
||
13. AST、语义检查、IR、source map。
|
||
14. ABB、FANUC、KUKA 后处理原型。
|
||
|
||
P1 扩展:
|
||
|
||
1. `label/jump` 和品牌标签程序导入。
|
||
2. `trap`、`interrupt`。
|
||
3. 多任务 `task`。
|
||
4. 更完整的 IO 类型。
|
||
5. 工艺模板库。
|
||
6. 品牌程序导入。
|
||
7. 复杂品牌扩展和转换报告。
|
||
|
||
## 25. 参考资料
|
||
|
||
1. ABB RAPID Technical Reference Manual,RAPID Instructions, Functions and Data Types:
|
||
https://library.e.abb.com/public/b227fcd260204c4dbeb8a58f8002fe64/Rapid_instructions.pdf
|
||
|
||
2. ABB RAPID Overview:
|
||
https://search.abb.com/library/Download.aspx?Action=Launch&DocumentID=3HAC050947-001&DocumentPartId=&LanguageCode=en
|
||
|
||
3. KUKA System Software,说明 KSS 支持 InLine forms 和 KRL 专家编程:
|
||
https://www.kuka.com/de-de/produkte-leistungen/robotersysteme/software/systemsoftware/kuka_systemsoftware
|
||
|
||
4. KUKA Application and Robot Programming,说明 KRL、Sunrise programming、simulation/offline programming 等工作流:
|
||
https://www.kuka.com/en-de/services/service_robots-and-machines/installation-start-up-and-programming-of-robots/application-and-robot-programming
|
||
|
||
5. FANUC PLC Motion Interface,说明 FANUC 可从上位控制发起 linear、joint、circular robot motion,并管理 speeds 与 termination types:
|
||
https://www.fanucamerica.com/products/software/plc-motion-interface
|
||
|
||
6. FANUC ROBOGUIDE,说明 FANUC 离线编程可生成机器人程序,并支持 CAD to Path、仿真和路径开发:
|
||
https://www.fanucamerica.com/products/software/roboguide
|
||
|
||
7. FANUC ASCII Program Loader,说明 FANUC LS 可读程序可编译为 TP 程序:
|
||
https://www.fanucamerica.com/products/controller-series/r-50ia
|