152 lines
4.6 KiB
TypeScript
152 lines
4.6 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import type { GrlDataDeclaration, GrlTargetDeclaration } from "../../src/grl/ast/index.js";
|
|
import { parseGrl } from "../../src/grl/parser/index.js";
|
|
import {
|
|
compileGrlDataDeclaration,
|
|
compileGrlTargetDeclaration,
|
|
compileOffsetExpression
|
|
} from "../../src/grl/semantic/index.js";
|
|
|
|
function dataDeclarations(source: string): GrlDataDeclaration[] {
|
|
return parseGrl(source).module.declarations.filter(
|
|
(declaration): declaration is GrlDataDeclaration => declaration.kind === "DataDeclaration"
|
|
);
|
|
}
|
|
|
|
function targetDeclarations(source: string): GrlTargetDeclaration[] {
|
|
return parseGrl(source).module.declarations.filter(
|
|
(declaration): declaration is GrlTargetDeclaration => declaration.kind === "TargetDeclaration"
|
|
);
|
|
}
|
|
|
|
describe("GRL data declarations and target compilation", () => {
|
|
it("compiles tool and frame declarations into shared structures", () => {
|
|
const [toolDecl, frameDecl] = dataDeclarations(`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,
|
|
cog: [0 mm, 0 mm, 80 mm]
|
|
}
|
|
persistent frame fixture = frame {
|
|
origin: pose(800 mm, 0 mm, 200 mm, 0 deg, 0 deg, 0 deg)
|
|
}
|
|
end
|
|
`);
|
|
|
|
expect(toolDecl).toMatchObject({
|
|
storage: "persistent",
|
|
typeName: "tool",
|
|
name: "gripper",
|
|
initializer: { kind: "ObjectExpression", typeName: "tool" }
|
|
});
|
|
expect(compileGrlDataDeclaration(toolDecl!)).toMatchObject({
|
|
name: "gripper",
|
|
value: {
|
|
tcp: {
|
|
position: [0, 0, 0.18],
|
|
quaternion: [0, 0, 0, 1]
|
|
},
|
|
mass: 2.5,
|
|
cog: [0, 0, 0.08]
|
|
}
|
|
});
|
|
expect(compileGrlDataDeclaration(frameDecl!)).toMatchObject({
|
|
name: "fixture",
|
|
value: {
|
|
origin: {
|
|
position: [0.8, 0, 0.2],
|
|
quaternion: [0, 0, 0, 1]
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
it("compiles speed and zone declarations", () => {
|
|
const declarations = dataDeclarations(`language grl 0.1
|
|
module Main
|
|
const speed v_joint = joint(80 %)
|
|
const speed v_pick = linear(300 mm/s)
|
|
const speed v_slow = linear(100 mm/s, acc 500 mm/s2)
|
|
const zone z_fine = fine
|
|
const zone z10 = z(10 mm)
|
|
const zone z_cnt = cnt(30)
|
|
const zone z_cont = continuous
|
|
end
|
|
`);
|
|
const compiled = declarations.map(compileGrlDataDeclaration);
|
|
|
|
expect(compiled).toMatchObject([
|
|
{ name: "v_joint", value: { kind: "joint_percent", value: 0.8 } },
|
|
{ name: "v_pick", value: { kind: "linear", velocity: 0.3 } },
|
|
{ name: "v_slow", value: { kind: "linear", velocity: 0.1, acceleration: 0.5 } },
|
|
{ name: "z_fine", value: { kind: "fine" } },
|
|
{ name: "z10", value: { kind: "distance", value: 0.01 } },
|
|
{ name: "z_cnt", value: { kind: "cnt", value: 30 } },
|
|
{ name: "z_cont", value: { kind: "continuous" } }
|
|
]);
|
|
});
|
|
|
|
it("compiles joint_target and pose_target declarations", () => {
|
|
const [home, pick] = targetDeclarations(`language grl 0.1
|
|
module Main
|
|
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
|
|
}
|
|
end
|
|
`);
|
|
|
|
expect(compileGrlTargetDeclaration(home!)).toMatchObject({
|
|
name: "home",
|
|
target: {
|
|
joints: [0, -Math.PI / 6, Math.PI / 3, 0, Math.PI / 3, 0]
|
|
}
|
|
});
|
|
|
|
const compiledPick = compileGrlTargetDeclaration(pick!);
|
|
expect(compiledPick.name).toBe("pick");
|
|
expect("pose" in compiledPick.target).toBe(true);
|
|
if ("pose" in compiledPick.target) {
|
|
expect(compiledPick.target.pose.position).toEqual([0.5, 0.12, 0.3]);
|
|
expect(compiledPick.target.config).toEqual({ shoulder: 0, elbow: 0, wrist: 1 });
|
|
}
|
|
});
|
|
|
|
it("parses and compiles offset expressions", () => {
|
|
const [declFrame, declTool] = dataDeclarations(`language grl 0.1
|
|
module Main
|
|
var pose_target p2 = pick offset x 20 mm y -10 mm z 50 mm
|
|
var pose_target p3 = pick offset_in tool z -50 mm
|
|
end
|
|
`);
|
|
|
|
expect(declFrame?.initializer).toMatchObject({
|
|
kind: "OffsetExpression",
|
|
mode: "frame",
|
|
axes: [
|
|
{ axis: "x" },
|
|
{ axis: "y" },
|
|
{ axis: "z" }
|
|
]
|
|
});
|
|
if (declFrame?.initializer.kind === "OffsetExpression") {
|
|
expect(compileOffsetExpression(declFrame.initializer)).toEqual({
|
|
mode: "frame",
|
|
xyz: [0.02, -0.01, 0.05]
|
|
});
|
|
}
|
|
if (declTool?.initializer.kind === "OffsetExpression") {
|
|
expect(compileOffsetExpression(declTool.initializer)).toEqual({
|
|
mode: "tool",
|
|
xyz: [0, 0, -0.05]
|
|
});
|
|
}
|
|
});
|
|
});
|