Optimize XYZAC motion updates and persist power-off recovery

This commit is contained in:
2026-08-29 04:52:44 +08:00
parent a97971ea19
commit f6e545018e
17 changed files with 479 additions and 74 deletions

View File

@@ -56,6 +56,41 @@ function payload<T>(message: MessageEnvelope): T {
function projection(result: Record<string, unknown>, message: MessageEnvelope, previous: FrontendState) {
const panel = result.panel_snapshot as PanelSnapshotV1 | undefined;
const delta = result.motion_sample as { tick?: number; pose?: Record<string, number>; joints?: number[]; active_segment_id?: number; active_progress?: number } | undefined;
if (!panel && delta && previous.snapshot) {
const pose = delta.pose ?? {};
const joints = Array.isArray(delta.joints) ? [...delta.joints] : previous.snapshot.motion?.joints ?? [];
const visual = previous.snapshot.visual ? {
...previous.snapshot.visual,
pose: { ...previous.snapshot.visual.pose, ...pose },
joints,
...(delta.active_segment_id !== undefined ? { active_segment_id: delta.active_segment_id } : {}),
...(delta.active_progress !== undefined ? { active_progress: delta.active_progress } : {}),
...(Array.isArray(result.motion_trace) ? { motion_trace: result.motion_trace } : {}),
} : previous.snapshot.visual;
const nextSnapshot = {
...previous.snapshot,
simulation_tick: message.simulation_tick ?? delta.tick ?? previous.snapshot.simulation_tick,
state_hash: String(result.state_hash ?? previous.snapshot.state_hash),
task: (result.task as SimSnapshotV1["task"]) ?? previous.snapshot.task,
program: (result.program as Record<string, unknown>) ?? previous.snapshot.program,
motion: {
...previous.snapshot.motion,
axes: [Number(pose.x ?? previous.snapshot.motion?.axes?.[0] ?? 0), Number(pose.y ?? previous.snapshot.motion?.axes?.[1] ?? 0), Number(pose.z ?? previous.snapshot.motion?.axes?.[2] ?? 0)],
joints,
},
wasm_motion: (result.wasm_motion as Record<string, unknown>) ?? previous.snapshot.wasm_motion,
...(visual ? { visual } : {}),
} satisfies SimSnapshotV1;
return {
snapshot: nextSnapshot,
toolpath: previous.toolpath,
task: (result.task as Record<string, unknown>) ?? previous.task,
program: (result.program as Record<string, unknown>) ?? previous.program,
axisState: (result.axis_state as AxisStateView) ?? previous.axisState,
gates: (result.gates as FrontendState["gates"]) ?? previous.gates,
};
}
if (panel?.schema === "axis-panel-snapshot.v1") {
const visualSegments = (Array.isArray(panel.visual.toolpath) ? panel.visual.toolpath : previous.toolpath)
.filter((segment) => segment && typeof segment === "object" && Number.isSafeInteger((segment as { id?: unknown }).id ?? 0))
@@ -178,7 +213,8 @@ export function reduceFrontendState(state: FrontendState, message: MessageEnvelo
const projected = projection(value, message, state);
const taskState = String((value.task as Record<string, unknown> | undefined)?.state ?? "").toUpperCase();
const status = ["ESTOP", "FAULT"].includes(taskState) ? "blocked" : "error";
return { ...base, status, error: { code: String(value.code ?? "worker_error"), message: JSON.stringify(value) }, ...projected };
const readable = value.reason ?? value.gate_reason ?? value.message_key ?? value.code ?? "worker_error";
return { ...base, status, error: { code: String(value.code ?? "worker_error"), message: String(readable) }, ...projected };
}
default: return base;
}