404 lines
13 KiB
Markdown
404 lines
13 KiB
Markdown
# 02-项目程序开发详细步骤
|
||
|
||
版本:0.1
|
||
日期:2026-06-27
|
||
|
||
## 1. 开发原则
|
||
|
||
1. 先把 ABB120 fixture、测试程序、运行器和报告数据模型稳定下来,再扩展 UI。
|
||
2. 每个任务必须有自动化测试或可复核证据。
|
||
3. 运行链路以统一 GRL/IR 为中心,品牌程序只作为输入输出格式。
|
||
4. HTML 虚拟控制器先接入现有 runtime/facade,避免在 UI 中重复实现业务逻辑。
|
||
5. 对标 ABB RobotStudio 的工程流程,不复制视觉资产和品牌资源。
|
||
6. GRL 运算功能必须贯穿 parser、AST、常量求值、语义编译和 motion/path 编译,不接受只解析不求值的半成品。
|
||
|
||
## 2. 阶段 0:基准资产整理
|
||
|
||
### A120-001:固化 ABB120 URDF fixture
|
||
|
||
步骤:
|
||
|
||
1. 将 `ABB_IRB120_3_58_URDF` 从测试 fixture 抽成可复用项目 fixture,或建立明确导出入口。
|
||
2. 保留来源记录:ROS-Industrial repository、branch、entrypoint、macro。
|
||
3. 增加 fixture 校验:base/tip、DOF、joint names、joint limits、fixed links。
|
||
4. 生成 `abb120.robot.json`,包含 URDF、load options、标准关节位和测试元数据。
|
||
|
||
验收:
|
||
|
||
1. `loadRobotFromUrdf` 能加载 ABB120。
|
||
2. `getRobotInfo` 输出 6 轴链。
|
||
3. 限位和标准关节位在范围内。
|
||
|
||
### A120-002:建立测试目录结构
|
||
|
||
建议新增:
|
||
|
||
```text
|
||
kdl-wasm/web/tests/fixtures/abb120/
|
||
abb120.robot.ts
|
||
programs/
|
||
A120_00_Smoke.grl
|
||
A120_10_JointPickPlace.grl
|
||
A120_20_CartesianBlend.grl
|
||
A120_30_IOWaitPulse.grl
|
||
A120_40_ErrorDiagnostics.grl
|
||
A120_50_OperationProcess.grl
|
||
expected/
|
||
abb/
|
||
fanuc/
|
||
kuka/
|
||
reports/
|
||
```
|
||
|
||
验收:测试能通过稳定路径读取所有 fixture。
|
||
|
||
## 3. 阶段 1:GRL 运算表达式基础
|
||
|
||
### GRL-EXPR-001:表达式 AST 扩展
|
||
|
||
当前相关文件:
|
||
|
||
1. `kdl-wasm/web/src/grl/ast/ast.ts`
|
||
2. `kdl-wasm/web/src/grl/parser/expressionParser.ts`
|
||
3. `kdl-wasm/web/src/grl/parser/parser.ts`
|
||
4. `kdl-wasm/web/src/grl/semantic/compileData.ts`
|
||
5. `kdl-wasm/web/src/grl/semantic/compileMotion.ts`
|
||
|
||
步骤:
|
||
|
||
1. 在 AST 中新增 `UnaryExpression`、`BinaryExpression`、必要时新增 `LogicalExpression` 或统一二元节点。
|
||
2. 保留现有 `NumberLiteral`、`BooleanLiteral`、`StringLiteral`、`IdentifierExpression`、`CallExpression`、`ArrayExpression`、`ObjectExpression`、`OffsetExpression`。
|
||
3. 节点必须保留 source range,方便 diagnostic 和 source map。
|
||
4. 兼容当前 `linear(300 mm/s)`、`pose(...)`、`joint_target {...}`、`offset` 语法。
|
||
|
||
验收:
|
||
|
||
1. AST snapshot 能显示 `1 + 2 * 3` 的优先级树。
|
||
2. `-(10 mm)`、`not (a == b)`、`sin(30 deg)` source range 稳定。
|
||
3. 当前 parser 测试不回退。
|
||
|
||
### GRL-EXPR-002:表达式 parser 优先级
|
||
|
||
步骤:
|
||
|
||
1. 将 `expressionParser.ts` 从当前 primary/offset 解析扩展为递归下降或 Pratt parser。
|
||
2. 支持 `+ - * / mod`、比较、逻辑、括号、一元运算。
|
||
3. 函数调用参数内部允许完整表达式,例如 `linear(100 + 50 mm/s)`。
|
||
4. array/object 属性值允许完整表达式,例如 `joints: [(10 + 5) deg, -90 deg]`。
|
||
5. offset 轴值允许常量表达式,例如 `offset z (5 + 5) mm`,并在语义阶段求值。
|
||
|
||
验收:
|
||
|
||
1. `linear(100 + 50 mm/s)` 可 parse。
|
||
2. `pose(400 + 50 mm, 20 * 2 mm, sqrt(90000) mm, 0 deg, 0 deg, atan2(1, 1))` 可 parse。
|
||
3. `wait io.di[1] == true and not io.di[2] timeout 1 + 1 s` 的条件和 timeout 均可保留 source range。
|
||
4. 非法表达式输出 `GRL_EXPR_PARSE` 或现有 parse error,并定位行列。
|
||
|
||
### GRL-EXPR-003:常量求值器和单位系统
|
||
|
||
建议新增:
|
||
|
||
```text
|
||
kdl-wasm/web/src/grl/semantic/constantExpression.ts
|
||
kdl-wasm/web/tests/grl/expressionCompile.test.ts
|
||
```
|
||
|
||
步骤:
|
||
|
||
1. 实现 `evaluateConstantExpression(expression, context)`。
|
||
2. context 提供符号表、期望单位维度、默认单位和 diagnostic sink。
|
||
3. 支持 `pi`、`e`。
|
||
4. 支持 `sin/cos/tan/asin/acos/atan/atan2/sqrt/abs/pow/min/max/clamp/floor/ceil/round`。
|
||
5. 支持 `mm/mm/s/mm/s2/deg/rad/%/s/ms/kg` 归一化。
|
||
6. 做除零、函数定义域、单位不兼容、未知符号、未知函数和非常量表达式诊断。
|
||
|
||
验收:
|
||
|
||
1. `100 + 50 mm/s` 在速度上下文求值为 `0.15 m/s`。
|
||
2. `(10 + 5) deg` 在角度上下文求值为 `0.261799... rad`。
|
||
3. `clamp(20 mm, 1 mm, 10 mm)` 求值为 `0.01 m`。
|
||
4. `sqrt(-1)` 输出 `GRL_EXPR_DOMAIN`。
|
||
5. `10 mm + 2 s` 输出 `GRL_EXPR_UNIT_MISMATCH`。
|
||
|
||
### GRL-EXPR-004:数据声明和 target 编译接入
|
||
|
||
步骤:
|
||
|
||
1. 在 `compileData.ts` 中把原来只接受 `NumberLiteral` 的位置改为常量表达式求值。
|
||
2. 覆盖 `tool.tcp`、`tool.mass`、`frame.origin`、`speed`、`zone`。
|
||
3. 覆盖 `joint_target.joints`、`pose_target.pose`、`poseq`、`robot_config`。
|
||
4. 变量引用只允许引用已知 const/persistent 常量或已编译数据符号;需要静态值的位置遇到运行态变量报 `GRL_EXPR_NON_CONSTANT`。
|
||
|
||
验收:
|
||
|
||
1. `const speed v = linear(100 + 50 mm/s)` 编译为 `0.15 m/s`。
|
||
2. `const zone z = z(max(5 mm, 10 mm))` 编译为 `0.01 m`。
|
||
3. `target home = joint_target { joints: [(10 + 5) deg, -90 deg] }` 编译为弧度数组。
|
||
4. `target pick = pose_target { pose: pose(400 + 50 mm, 0 mm, sqrt(90000) mm, 0 deg, 0 deg, atan2(1, 1)) }` 编译通过。
|
||
|
||
### GRL-EXPR-005:motion/path/IO 编译接入
|
||
|
||
步骤:
|
||
|
||
1. 在 `compileMotion.ts` 中把内联 `speed`、`zone`、path defaults/source 属性改为常量表达式求值。
|
||
2. path point 的 `via`、`target`、`tool`、`frame` 若使用内联结构表达式,必须支持内部数值表达式。
|
||
3. path event `distance` 支持表达式。
|
||
4. IO/wait/pulse 中的 `timeout`、`duration` 支持表达式,归一化为秒。
|
||
5. runtime 条件中的比较/逻辑表达式至少保留结构化 AST 或稳定文本,并能在虚拟控制器 trace 中显示。
|
||
|
||
验收:
|
||
|
||
1. `point p0 movej home speed linear(100 + 50 mm/s) zone z(5 + 5 mm)` 编译到 KDL request。
|
||
2. `event at p0 distance 5 + 5 mm ...` 编译为 `0.01 m`。
|
||
3. `wait io.di[1] == true timeout 1 + 1 s` timeout 为 `2 s`。
|
||
4. `pulse io.do[1] duration 50 + 50 ms` duration 为 `0.1 s`。
|
||
|
||
### GRL-EXPR-006:三品牌后处理和报告边界
|
||
|
||
步骤:
|
||
|
||
1. 后处理器优先使用已求值 IR,不输出未折叠常量表达式。
|
||
2. ABB/FANUC/KUKA 输出速度、zone、pose、joint 值时,使用各品牌可接受的具体数值。
|
||
3. runtime 条件表达式如无法保真输出,转换报告记录 `GRL_EXPR_UNSUPPORTED_RUNTIME`。
|
||
4. roundtrip report 标注表达式已折叠,回读结果以数值等价为准。
|
||
|
||
验收:
|
||
|
||
1. `linear(100 + 50 mm/s)` 在 ABB/FANUC/KUKA 输出中体现为具体速度。
|
||
2. `z(clamp(...))` 输出具体 zone/CNT/C_DIS 近似,并在 report 记录近似。
|
||
3. 后处理 report 不允许静默丢失 runtime 逻辑表达式。
|
||
|
||
## 4. 阶段 2:通用机器人测试程序
|
||
|
||
### A120-010:编写 GRL 程序集
|
||
|
||
步骤:
|
||
|
||
1. 按 `01-项目功能内容.md` 第 3 章创建 6 个 GRL 程序。
|
||
2. 每个程序声明 `module`、`speed`、`zone`、`tool/frame` 需求和 source metadata。
|
||
3. 关节目标使用 fixture 标准关节位。
|
||
4. pose 目标由 FK 自动生成,避免手写不可达姿态误判。
|
||
5. 故障程序单独放入 error suite,不进入 happy path 汇总。
|
||
|
||
验收:
|
||
|
||
1. 所有 happy path 程序可 parse。
|
||
2. error suite 输出稳定 diagnostic。
|
||
3. source map 覆盖每个 motion、wait、io、operation。
|
||
|
||
### A120-011:建立程序 golden snapshot
|
||
|
||
步骤:
|
||
|
||
1. 保存 AST snapshot。
|
||
2. 保存 Semantic IR snapshot。
|
||
3. 保存 KDL bridge request snapshot。
|
||
4. 保存 source map snapshot。
|
||
|
||
验收:同一输入重复生成一致;非预期 diff 会导致测试失败。
|
||
|
||
## 5. 阶段 3:运行器和 KDL 全面测试
|
||
|
||
### A120-030:ABB120 KDL 基线测试
|
||
|
||
步骤:
|
||
|
||
1. 加载 ABB120 URDF。
|
||
2. 执行 `fk(home)`,校验 TCP 位置和姿态。
|
||
3. 执行 `fkAllLinks(home)`,校验 link 顺序。
|
||
4. 执行 `jacobian(pick)`,校验矩阵维度和有限值。
|
||
5. 执行 `checkJointLimits`,覆盖合法和非法关节。
|
||
6. 执行 `checkSingularity`,输出 manipulability 和 conditionNumber。
|
||
|
||
验收:测试报告包含 robot info、FK、link poses、Jacobian、limits、singularity。
|
||
|
||
### A120-031:轨迹规划测试
|
||
|
||
步骤:
|
||
|
||
1. 对 `A120_10_JointPickPlace` 执行 `planPath`。
|
||
2. 对 `A120_20_CartesianBlend` 执行 `planMoveL/planMoveC`。
|
||
3. 对故障路径执行 `validatePath`。
|
||
4. 输出轨迹点数、duration、max velocity、max acceleration、blend diagnostics。
|
||
|
||
验收:happy path `ok=true`;error path 有稳定 `code/severity/sourceMap`。
|
||
|
||
### A120-032:虚拟控制器运行测试
|
||
|
||
步骤:
|
||
|
||
1. `compileSemanticProgram` 得到 IR。
|
||
2. `VirtualController.load` 加载程序。
|
||
3. 分别执行 run、pause、step、stop、reset。
|
||
4. Motion Queue 绑定 KDL planner。
|
||
5. IO runtime 注入 DI script。
|
||
6. 记录 trace、program counter、scope、alarm、wait、motion activeIndex。
|
||
|
||
验收:控制器状态机合法;trace 可回放;wait 卡住和 timeout 可诊断。
|
||
|
||
### A120-033:job runner
|
||
|
||
步骤:
|
||
|
||
1. 新增 `runAbb120Suite` 或 CLI 脚本。
|
||
2. 输入:suite id、程序列表、robot fixture、输出目录。
|
||
3. 输出:`job_id`、`job.json`、`trace.json`、`trajectory.json`、`diagnostics.json`。
|
||
4. job id 格式:`A120-JOB-YYYYMMDD-HHMMSS-<short-hash>`。
|
||
|
||
验收:CI 可运行并生成稳定证据目录。
|
||
|
||
## 6. 阶段 4:跨品牌转换和回读
|
||
|
||
### A120-050:三品牌后处理 golden
|
||
|
||
步骤:
|
||
|
||
1. 对每个 happy path GRL 编译 IR。
|
||
2. 调用 `postProcessAllBrands`。
|
||
3. 生成 ABB `.mod`、FANUC `.ls`、KUKA `.src/.dat`。
|
||
4. 保存 golden 文件。
|
||
5. 生成 post report。
|
||
|
||
验收:
|
||
|
||
1. ABB 输出包含 `MoveJ/MoveL/MoveC/SetDO/WaitUntil/PulseDO`。
|
||
2. FANUC 输出包含 `J/L/C/DO/WAIT/PULSE`。
|
||
3. KUKA 输出包含 `PTP/LIN/CIRC/$OUT/WAIT FOR`。
|
||
4. unsupported/approximation 不允许静默丢失。
|
||
|
||
### A120-051:品牌导入回读
|
||
|
||
步骤:
|
||
|
||
1. 将后处理输出重新导入。
|
||
2. 对比 target 数量、motion 顺序、operation 结构。
|
||
3. 对不可逆语义生成 diff report。
|
||
4. 输出 `roundtrip.json`。
|
||
|
||
验收:happy path 结构等价;近似项全部进入 report。
|
||
|
||
## 7. 阶段 5:离线编程全面测试
|
||
|
||
### A120-070:OLP 项目生成
|
||
|
||
步骤:
|
||
|
||
1. 根据 ABB120 fixture 创建 Station。
|
||
2. 添加 Robot、Tool、Frame、Target、Path、Operation、Program。
|
||
3. 保存到 workspace。
|
||
4. 导出 bundle,再导入恢复。
|
||
|
||
验收:恢复后项目对象等价,manifest 完整。
|
||
|
||
### A120-071:验证报告
|
||
|
||
步骤:
|
||
|
||
1. 生成 reachability report。
|
||
2. 生成 cycle time report。
|
||
3. 生成 IO/Wait report。
|
||
4. 生成 collision report。
|
||
5. 生成 post/import report。
|
||
6. 汇总为 HTML report,预留 PDF/print。
|
||
|
||
验收:每个 report 有 `report_id`、status、summary、sections、diagnostics、source map。
|
||
|
||
### A120-072:客户交付包
|
||
|
||
步骤:
|
||
|
||
1. 打包 GRL 源程序。
|
||
2. 打包 ABB/FANUC/KUKA 输出程序。
|
||
3. 打包 IO map、校准数据、trace、trajectory、report。
|
||
4. 输出 bundle manifest。
|
||
|
||
验收:交付包可解包并追溯每个输出来源。
|
||
|
||
## 8. 阶段 6:HTML 虚拟控制器
|
||
|
||
### A120-090:页面骨架
|
||
|
||
建议新增:
|
||
|
||
```text
|
||
kdl-wasm/web/app/virtual-controller.html
|
||
kdl-wasm/web/app/virtual-controller.css
|
||
kdl-wasm/web/app/virtual-controller.js
|
||
kdl-wasm/web/scripts/verify-virtual-controller.mjs
|
||
```
|
||
|
||
步骤:
|
||
|
||
1. 页面直接进入 ABB120 工作台。
|
||
2. 顶部命令栏、左侧对象树、中央 station viewport、右侧示教器、底部诊断面板。
|
||
3. 接入 WorkbenchFacade 和 VirtualController snapshot。
|
||
4. 无数据时显示空工程状态;加载 fixture 后显示对象树和程序。
|
||
|
||
验收:浏览器直接打开 HTML 即可看到 ABB120 项目工作台;`npm run verify:virtual-controller` 能生成桌面和移动截图证据。
|
||
|
||
### A120-091:运行控制
|
||
|
||
步骤:
|
||
|
||
1. 实现 Load、Run、Pause、Step、Stop、Reset。
|
||
2. 显示状态灯、mode、motors、program pointer、cycle time。
|
||
3. 显示 joint/TCP 值。
|
||
4. Motion Queue 与时间轴同步。
|
||
|
||
验收:按钮触发 runtime 状态变化,页面数据同步。
|
||
|
||
### A120-092:编辑器和 source map
|
||
|
||
步骤:
|
||
|
||
1. GRL/ABB/FANUC/KUKA 多标签只读查看。
|
||
2. 当前执行行高亮。
|
||
3. 点击诊断跳转源码。
|
||
4. 点击 path point 高亮 viewport 和 source。
|
||
|
||
验收:source map 双向定位可用。
|
||
|
||
### A120-093:IO、Wait、报警和报告
|
||
|
||
步骤:
|
||
|
||
1. IO 面板显示 DI/DO 当前值和最近事件。
|
||
2. wait 面板显示表达式、elapsed、remaining timeout、子表达式值。
|
||
3. alarm 面板显示 severity、code、source。
|
||
4. report 面板打开 HTML report。
|
||
|
||
验收:wait 卡住时可以定位并手动置位 DI 继续运行。
|
||
|
||
### A120-094:视觉验证
|
||
|
||
步骤:
|
||
|
||
1. 使用 Playwright 打开 HTML 页面。
|
||
2. 截图桌面和移动视口。
|
||
3. 如果有 canvas/3D,做非空像素检查。
|
||
4. 保存截图到证据目录。
|
||
|
||
验收:页面无重叠、核心文字不溢出、主要面板可见。
|
||
|
||
## 9. 阶段 7:全量验收
|
||
|
||
### A120-900:CI 全量命令
|
||
|
||
命令:
|
||
|
||
```bash
|
||
cd /home/meswork/kdl_work
|
||
npm run typecheck
|
||
npm test
|
||
cmake --build kdl-wasm/build-wasm -j16
|
||
```
|
||
|
||
新增后还应包含:
|
||
|
||
```bash
|
||
npm run test -- abb120
|
||
npm run test -- post import workbench controller runtime reports
|
||
```
|
||
|
||
验收:所有测试通过,`05-验收证据.md` 记录 job/report/screenshot 路径。
|