同步KDL工程源码到云仓库
This commit is contained in:
149
kdl-wasm/web/tests/grl/generator/roundtrip.test.ts
Normal file
149
kdl-wasm/web/tests/grl/generator/roundtrip.test.ts
Normal file
@@ -0,0 +1,149 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { generateGrlProgram, type GrlProgramGenerationSpec } from "../../../src/grl/generator/index.js";
|
||||
import { postProcessAllBrands } from "../../../src/grl/post/index.js";
|
||||
import type { GrlOperationDeclaration, GrlPathDeclaration, GrlTargetDeclaration } from "../../../src/grl/ast/index.js";
|
||||
import { parseGrl } from "../../../src/grl/parser/index.js";
|
||||
import { compileSemanticProgram } from "../../../src/grl/semantic/index.js";
|
||||
|
||||
const SPEC: GrlProgramGenerationSpec = {
|
||||
moduleName: "GeneratedCell",
|
||||
speeds: {
|
||||
v_linear: "linear(200 mm/s)",
|
||||
v_joint: "joint(50 %)"
|
||||
},
|
||||
zones: {
|
||||
z10: "z(10 mm)",
|
||||
zf: "fine"
|
||||
},
|
||||
targets: [
|
||||
{ name: "pick", kind: "pose", values: [500, 0, 0, 0, 0, 0] },
|
||||
{ name: "home", kind: "joint", values: [0] },
|
||||
{ name: "place", kind: "pose", values: [600, 0, 0, 0, 0, 0] }
|
||||
],
|
||||
path: {
|
||||
name: "generated_path",
|
||||
source: {
|
||||
type: "cad_curve",
|
||||
id: "edge_001",
|
||||
sample_distance: 5
|
||||
},
|
||||
defaults: {
|
||||
speed: "v_linear",
|
||||
zone: "z10"
|
||||
},
|
||||
points: [
|
||||
{ motion: "movej", target: "home", speed: "v_joint", zone: "zf" },
|
||||
{ motion: "movel", target: "pick" },
|
||||
{ id: "place_point", motion: "movel", target: "place", zone: "zf" }
|
||||
]
|
||||
},
|
||||
operation: {
|
||||
name: "generated_op",
|
||||
kind: "handling",
|
||||
path: "generated_path",
|
||||
startAction: "io.do[1] = true",
|
||||
endAction: "io.do[1] = false"
|
||||
}
|
||||
};
|
||||
|
||||
describe("GRL generator and roundtrip", () => {
|
||||
it("generates stable expanded GRL with target/path/operation first", () => {
|
||||
const first = generateGrlProgram(SPEC, "expanded");
|
||||
const second = generateGrlProgram(SPEC, "expanded");
|
||||
|
||||
expect(first).toEqual(second);
|
||||
expect(first.stableIds).toEqual({
|
||||
targets: ["home", "pick", "place"],
|
||||
points: ["p00", "p01", "place_point"],
|
||||
path: "generated_path",
|
||||
operation: "generated_op"
|
||||
});
|
||||
expect(first.text).toBe(`language grl 0.1
|
||||
module GeneratedCell
|
||||
const speed v_joint = joint(50 %)
|
||||
const speed v_linear = linear(200 mm/s)
|
||||
const zone z10 = z(10 mm)
|
||||
const zone zf = fine
|
||||
target home = joint_target {
|
||||
joints: [0 deg]
|
||||
}
|
||||
target pick = pose_target {
|
||||
pose: pose(500 mm, 0 mm, 0 mm, 0 deg, 0 deg, 0 deg)
|
||||
}
|
||||
target place = pose_target {
|
||||
pose: pose(600 mm, 0 mm, 0 mm, 0 deg, 0 deg, 0 deg)
|
||||
}
|
||||
path generated_path {
|
||||
source {
|
||||
id: "edge_001"
|
||||
sample_distance: 5
|
||||
type: cad_curve
|
||||
}
|
||||
defaults {
|
||||
speed: v_linear
|
||||
zone: z10
|
||||
}
|
||||
point p00 movej home speed v_joint zone zf
|
||||
point p01 movel pick
|
||||
point place_point movel place zone zf
|
||||
}
|
||||
operation generated_op {
|
||||
kind: handling
|
||||
path: generated_path
|
||||
start_action:
|
||||
io.do[1] = true
|
||||
end_action:
|
||||
io.do[1] = false
|
||||
}
|
||||
proc main()
|
||||
run_operation generated_op
|
||||
end
|
||||
end`);
|
||||
});
|
||||
|
||||
it("supports compact output that remains parseable", () => {
|
||||
const compact = generateGrlProgram(SPEC, "compact");
|
||||
|
||||
expect(compact.text).toContain("path generated_path { source { id: \"edge_001\"");
|
||||
expect(parseGrl(compact.text).module.name).toBe("GeneratedCell");
|
||||
});
|
||||
|
||||
it("roundtrips through parser, semantic IR, and postprocessors", () => {
|
||||
const generated = generateGrlProgram(SPEC, "expanded");
|
||||
const ast = parseGrl(generated.text);
|
||||
const declarations = ast.module.declarations;
|
||||
const targets = declarations.filter((decl): decl is GrlTargetDeclaration => decl.kind === "TargetDeclaration");
|
||||
const path = declarations.find((decl): decl is GrlPathDeclaration => decl.kind === "PathDeclaration")!;
|
||||
const operation = declarations.find((decl): decl is GrlOperationDeclaration => decl.kind === "OperationDeclaration")!;
|
||||
const ir = compileSemanticProgram(ast, {
|
||||
startJoints: [0],
|
||||
sampleTime: 0.004
|
||||
});
|
||||
const post = postProcessAllBrands(ir);
|
||||
|
||||
expect(targets.map((target) => target.name)).toEqual(["home", "pick", "place"]);
|
||||
expect(path.items).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ kind: "PathSourceBlock" }),
|
||||
expect.objectContaining({ kind: "PathDefaultsBlock" }),
|
||||
expect.objectContaining({ kind: "PathPoint", id: "p00" }),
|
||||
expect.objectContaining({ kind: "PathPoint", id: "p01" }),
|
||||
expect.objectContaining({ kind: "PathPoint", id: "place_point" })
|
||||
])
|
||||
);
|
||||
expect(operation).toMatchObject({
|
||||
name: "generated_op",
|
||||
operationKind: "handling",
|
||||
pathName: "generated_path"
|
||||
});
|
||||
expect(ir.symbols).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ kind: "path", name: "generated_path" }),
|
||||
expect.objectContaining({ kind: "operation", name: "generated_op" })
|
||||
])
|
||||
);
|
||||
expect(post.outputs.abb.text).toContain("MODULE GeneratedCell");
|
||||
expect(post.outputs.fanuc.text).toContain("/PROG MAIN");
|
||||
expect(post.outputs.kuka.text).toContain("DEF Main()");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user