继续完成 web-rtcp-5axis-sim-plan
结论:完成 LinuxCNC kinematics WASM ABI 覆盖,并将 web-rtcp-5axis-sim-plan 的 RTCP frame/boundary adapter 接到 xyzac-trt kinematics SDK;Node、build、browser smoke 验证通过。
This commit is contained in:
@@ -1,5 +1,10 @@
|
||||
export { createLinuxCncIniSdk } from "./linuxcnc-ini.js";
|
||||
export { createLinuxCncInterpSdk } from "./linuxcnc-interp.js";
|
||||
export {
|
||||
createLinuxCncKinematicsSdk,
|
||||
linuxCncKinematicsWasmFile,
|
||||
supportedLinuxCncKinematicsModules,
|
||||
} from "./linuxcnc-kinematics.js";
|
||||
export {
|
||||
VIRTUAL_HAL_AXES,
|
||||
VIRTUAL_HAL_AXISUI_PINS,
|
||||
|
||||
206
wasm-port/runtime/sdk/src/linuxcnc-kinematics.js
Normal file
206
wasm-port/runtime/sdk/src/linuxcnc-kinematics.js
Normal file
@@ -0,0 +1,206 @@
|
||||
import createLinuxCncTrivkinsKinematicsModule from "../../../build/wasm/kinematics/linuxcnc_trivkins_kinematics.js";
|
||||
import createLinuxCnc5axiskinsKinematicsModule from "../../../build/wasm/kinematics/linuxcnc_5axiskins_kinematics.js";
|
||||
import createLinuxCncXyzacTrtKinematicsModule from "../../../build/wasm/kinematics/linuxcnc_xyzac_trt_kinematics.js";
|
||||
import createLinuxCncXyzbcTrtKinematicsModule from "../../../build/wasm/kinematics/linuxcnc_xyzbc_trt_kinematics.js";
|
||||
import createLinuxCncCorexyKinematicsModule from "../../../build/wasm/kinematics/linuxcnc_corexy_kinematics.js";
|
||||
import createLinuxCncRotateKinematicsModule from "../../../build/wasm/kinematics/linuxcnc_rotate_kinematics.js";
|
||||
import createLinuxCncRoseKinematicsModule from "../../../build/wasm/kinematics/linuxcnc_rose_kinematics.js";
|
||||
import createLinuxCncMaxKinematicsModule from "../../../build/wasm/kinematics/linuxcnc_max_kinematics.js";
|
||||
import createLinuxCncLineardeltaKinematicsModule from "../../../build/wasm/kinematics/linuxcnc_lineardelta_kinematics.js";
|
||||
import createLinuxCncRotarydeltaKinematicsModule from "../../../build/wasm/kinematics/linuxcnc_rotarydelta_kinematics.js";
|
||||
import createLinuxCncScorbotKinematicsModule from "../../../build/wasm/kinematics/linuxcnc_scorbot_kinematics.js";
|
||||
import createLinuxCncTripodKinematicsModule from "../../../build/wasm/kinematics/linuxcnc_tripod_kinematics.js";
|
||||
import createLinuxCncScaraKinematicsModule from "../../../build/wasm/kinematics/linuxcnc_scara_kinematics.js";
|
||||
import createLinuxCncPumaKinematicsModule from "../../../build/wasm/kinematics/linuxcnc_puma_kinematics.js";
|
||||
import createLinuxCncGenserKinematicsModule from "../../../build/wasm/kinematics/linuxcnc_genser_kinematics.js";
|
||||
import createLinuxCncGenhexKinematicsModule from "../../../build/wasm/kinematics/linuxcnc_genhex_kinematics.js";
|
||||
import createLinuxCncPentakinsKinematicsModule from "../../../build/wasm/kinematics/linuxcnc_pentakins_kinematics.js";
|
||||
|
||||
export const LINUXCNC_KINEMATICS_MODULES = [
|
||||
{ id: "trivkins", wasmFile: "linuxcnc_trivkins_kinematics.wasm", factory: createLinuxCncTrivkinsKinematicsModule },
|
||||
{ id: "5axiskins", wasmFile: "linuxcnc_5axiskins_kinematics.wasm", factory: createLinuxCnc5axiskinsKinematicsModule },
|
||||
{ id: "xyzac-trt", wasmFile: "linuxcnc_xyzac_trt_kinematics.wasm", factory: createLinuxCncXyzacTrtKinematicsModule },
|
||||
{ id: "xyzbc-trt", wasmFile: "linuxcnc_xyzbc_trt_kinematics.wasm", factory: createLinuxCncXyzbcTrtKinematicsModule },
|
||||
{ id: "corexy", wasmFile: "linuxcnc_corexy_kinematics.wasm", factory: createLinuxCncCorexyKinematicsModule },
|
||||
{ id: "rotate", wasmFile: "linuxcnc_rotate_kinematics.wasm", factory: createLinuxCncRotateKinematicsModule },
|
||||
{ id: "rose", wasmFile: "linuxcnc_rose_kinematics.wasm", factory: createLinuxCncRoseKinematicsModule },
|
||||
{ id: "max", wasmFile: "linuxcnc_max_kinematics.wasm", factory: createLinuxCncMaxKinematicsModule },
|
||||
{ id: "lineardelta", wasmFile: "linuxcnc_lineardelta_kinematics.wasm", factory: createLinuxCncLineardeltaKinematicsModule },
|
||||
{ id: "rotarydelta", wasmFile: "linuxcnc_rotarydelta_kinematics.wasm", factory: createLinuxCncRotarydeltaKinematicsModule },
|
||||
{ id: "scorbot", wasmFile: "linuxcnc_scorbot_kinematics.wasm", factory: createLinuxCncScorbotKinematicsModule },
|
||||
{ id: "tripod", wasmFile: "linuxcnc_tripod_kinematics.wasm", factory: createLinuxCncTripodKinematicsModule },
|
||||
{ id: "scara", wasmFile: "linuxcnc_scara_kinematics.wasm", factory: createLinuxCncScaraKinematicsModule },
|
||||
{ id: "puma", wasmFile: "linuxcnc_puma_kinematics.wasm", factory: createLinuxCncPumaKinematicsModule },
|
||||
{ id: "genser", wasmFile: "linuxcnc_genser_kinematics.wasm", factory: createLinuxCncGenserKinematicsModule },
|
||||
{ id: "genhex", wasmFile: "linuxcnc_genhex_kinematics.wasm", factory: createLinuxCncGenhexKinematicsModule },
|
||||
{ id: "pentakins", wasmFile: "linuxcnc_pentakins_kinematics.wasm", factory: createLinuxCncPentakinsKinematicsModule },
|
||||
];
|
||||
|
||||
const MODULES_BY_ID = new Map(LINUXCNC_KINEMATICS_MODULES.map((entry) => [entry.id, entry]));
|
||||
|
||||
function requireWasmFunction(mod, functionName) {
|
||||
const fn = mod[`_${functionName}`];
|
||||
if (typeof fn !== "function") {
|
||||
throw new Error(`linuxcnc kinematics WASM missing ${functionName}; rebuild wasm-port/tools/build_kinematics_wasm.sh`);
|
||||
}
|
||||
return fn;
|
||||
}
|
||||
|
||||
function writeDoubleArray(mod, values) {
|
||||
const bytes = values.length * 8;
|
||||
const ptr = mod._malloc(bytes);
|
||||
mod.HEAPF64.set(values, ptr / 8);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
function readDoubleArray(mod, ptr, length) {
|
||||
return Array.from(mod.HEAPF64.subarray(ptr / 8, ptr / 8 + length));
|
||||
}
|
||||
|
||||
function poseValuesFromObject(pose = {}) {
|
||||
return [
|
||||
Number(pose.x ?? pose.tran?.x ?? 0),
|
||||
Number(pose.y ?? pose.tran?.y ?? 0),
|
||||
Number(pose.z ?? pose.tran?.z ?? 0),
|
||||
Number(pose.a ?? 0),
|
||||
Number(pose.b ?? 0),
|
||||
Number(pose.c ?? 0),
|
||||
Number(pose.u ?? 0),
|
||||
Number(pose.v ?? 0),
|
||||
Number(pose.w ?? 0),
|
||||
];
|
||||
}
|
||||
|
||||
function poseObjectFromValues(values) {
|
||||
return {
|
||||
x: values[0],
|
||||
y: values[1],
|
||||
z: values[2],
|
||||
a: values[3],
|
||||
b: values[4],
|
||||
c: values[5],
|
||||
u: values[6],
|
||||
v: values[7],
|
||||
w: values[8],
|
||||
};
|
||||
}
|
||||
|
||||
export function supportedLinuxCncKinematicsModules() {
|
||||
return LINUXCNC_KINEMATICS_MODULES.map((entry) => entry.id);
|
||||
}
|
||||
|
||||
export function linuxCncKinematicsWasmFile(moduleId) {
|
||||
return MODULES_BY_ID.get(moduleId)?.wasmFile || null;
|
||||
}
|
||||
|
||||
export async function createLinuxCncKinematicsSdk({
|
||||
moduleId = "xyzac-trt",
|
||||
moduleOptions = {},
|
||||
} = {}) {
|
||||
const entry = MODULES_BY_ID.get(moduleId);
|
||||
if (!entry) {
|
||||
throw new Error(`unsupported LinuxCNC kinematics module: ${moduleId}`);
|
||||
}
|
||||
|
||||
const mod = await entry.factory(moduleOptions);
|
||||
requireWasmFunction(mod, "lckins_init")();
|
||||
|
||||
return {
|
||||
apiName: "linuxcnc-kinematics-wasm-sdk",
|
||||
moduleId,
|
||||
module: mod,
|
||||
wasmFile: entry.wasmFile,
|
||||
|
||||
hasWasmFunction(functionName) {
|
||||
return typeof mod[`_${functionName}`] === "function";
|
||||
},
|
||||
|
||||
type() {
|
||||
return requireWasmFunction(mod, "lckins_type")();
|
||||
},
|
||||
|
||||
switchable() {
|
||||
return requireWasmFunction(mod, "lckins_switchable")();
|
||||
},
|
||||
|
||||
switchKinematics(switchkinsType) {
|
||||
return requireWasmFunction(mod, "lckins_switch")(Number(switchkinsType) || 0);
|
||||
},
|
||||
|
||||
forward(joints, options = {}) {
|
||||
const jointValues = Array.from(joints, Number);
|
||||
const jointsPtr = writeDoubleArray(mod, jointValues);
|
||||
const posePtr = writeDoubleArray(mod, poseValuesFromObject(options.seedPose));
|
||||
const fflagsPtr = mod._malloc(8);
|
||||
const iflagsPtr = mod._malloc(8);
|
||||
mod.HEAPU32[fflagsPtr / 4] = 0;
|
||||
mod.HEAPU32[iflagsPtr / 4] = 0;
|
||||
try {
|
||||
const rc = requireWasmFunction(mod, "lckins_forward")(
|
||||
jointsPtr,
|
||||
jointValues.length,
|
||||
posePtr,
|
||||
fflagsPtr,
|
||||
iflagsPtr,
|
||||
);
|
||||
return {
|
||||
rc,
|
||||
pose: poseObjectFromValues(readDoubleArray(mod, posePtr, 9)),
|
||||
fflags: mod.HEAPU32[fflagsPtr / 4],
|
||||
iflags: mod.HEAPU32[iflagsPtr / 4],
|
||||
};
|
||||
} finally {
|
||||
mod._free(jointsPtr);
|
||||
mod._free(posePtr);
|
||||
mod._free(fflagsPtr);
|
||||
mod._free(iflagsPtr);
|
||||
}
|
||||
},
|
||||
|
||||
inverse(pose, jointCount = 5, options = {}) {
|
||||
const posePtr = writeDoubleArray(mod, poseValuesFromObject(pose));
|
||||
const jointsPtr = mod._malloc(jointCount * 8);
|
||||
const iflagsPtr = mod._malloc(8);
|
||||
const fflagsPtr = mod._malloc(8);
|
||||
const seedJoints = Array.isArray(options.seedJoints)
|
||||
? options.seedJoints.map(Number)
|
||||
: [];
|
||||
mod.HEAPF64.fill(0, jointsPtr / 8, jointsPtr / 8 + jointCount);
|
||||
mod.HEAPF64.set(seedJoints.slice(0, jointCount), jointsPtr / 8);
|
||||
mod.HEAPU32[iflagsPtr / 4] = 0;
|
||||
mod.HEAPU32[fflagsPtr / 4] = 0;
|
||||
try {
|
||||
const rc = requireWasmFunction(mod, "lckins_inverse")(
|
||||
posePtr,
|
||||
jointsPtr,
|
||||
jointCount,
|
||||
iflagsPtr,
|
||||
fflagsPtr,
|
||||
);
|
||||
return {
|
||||
rc,
|
||||
joints: readDoubleArray(mod, jointsPtr, jointCount),
|
||||
iflags: mod.HEAPU32[iflagsPtr / 4],
|
||||
fflags: mod.HEAPU32[fflagsPtr / 4],
|
||||
};
|
||||
} finally {
|
||||
mod._free(posePtr);
|
||||
mod._free(jointsPtr);
|
||||
mod._free(iflagsPtr);
|
||||
mod._free(fflagsPtr);
|
||||
}
|
||||
},
|
||||
|
||||
runProbe() {
|
||||
const resultPtr = requireWasmFunction(mod, "lckins_run_probe")();
|
||||
if (!resultPtr) {
|
||||
throw new Error("lckins_run_probe returned null");
|
||||
}
|
||||
try {
|
||||
return mod.UTF8ToString(resultPtr);
|
||||
} finally {
|
||||
requireWasmFunction(mod, "lckins_free_string")(resultPtr);
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user