继续完成 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:
2026-06-21 16:44:29 +08:00
parent a6eda3fbff
commit 626bcfe8e3
101 changed files with 101586 additions and 770 deletions

View File

@@ -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,

View 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);
}
},
};
}