Preserve motion queue ABI for feed override

This commit is contained in:
2026-08-31 06:36:53 +08:00
parent 51ba923cb5
commit 6033dcd47a
4 changed files with 10 additions and 9 deletions

View File

@@ -30,10 +30,11 @@ typedef struct sim_motion_command {
sim_posemath_segment segment;
uint32_t id;
uint32_t tag;
uint32_t flags;
} sim_motion_command;
#define SIM_MOTION_COMMAND_FLAG_RAPID 1u
/* The high tag bit is reserved for Rapid blocks so the command ABI remains
compatible with existing checkpoints and WASM clients. */
#define SIM_MOTION_COMMAND_TAG_RAPID (UINT32_C(1) << 31)
typedef struct sim_motion_state {
sim_posemath_pose position;

View File

@@ -184,11 +184,11 @@ static double planned_velocity(const sim_motion_queue *queue, uint32_t offset) {
uint32_t index;
if (queue == NULL || offset >= queue->count) return 0.0;
index = (queue->head + offset) % SIM_MOTION_QUEUE_CAPACITY;
velocity = queue->commands[index].segment.velocity * (meta == NULL || (queue->commands[index].flags & SIM_MOTION_COMMAND_FLAG_RAPID) != 0u ? 1.0 : meta->feed_override);
velocity = queue->commands[index].segment.velocity * (meta == NULL || (queue->commands[index].tag & SIM_MOTION_COMMAND_TAG_RAPID) != 0u ? 1.0 : meta->feed_override);
if (meta == NULL || meta->profile == SIM_MOTION_PROFILE_EXACT_STOP) return velocity;
for (index = 1; index <= meta->lookahead && offset + index < queue->count; ++index) {
uint32_t next = (queue->head + offset + index) % SIM_MOTION_QUEUE_CAPACITY;
const double next_velocity = queue->commands[next].segment.velocity * ((queue->commands[next].flags & SIM_MOTION_COMMAND_FLAG_RAPID) != 0u ? 1.0 : meta->feed_override);
const double next_velocity = queue->commands[next].segment.velocity * ((queue->commands[next].tag & SIM_MOTION_COMMAND_TAG_RAPID) != 0u ? 1.0 : meta->feed_override);
if (next_velocity < velocity) velocity = next_velocity;
}
return velocity;
@@ -232,7 +232,7 @@ int sim_motion_step(sim_motion_queue *queue) {
command = &queue->commands[queue->head];
length = segment_length(&command->segment);
if (length <= 0.0) { queue->state.status = SIM_MOTION_ERR_GEOMETRY; return queue->state.status; }
queue->state.active_id = command->id; queue->state.active_tag = command->tag; queue->state.motion_type = command->segment.motion_type;
queue->state.active_id = command->id; queue->state.active_tag = command->tag & ~SIM_MOTION_COMMAND_TAG_RAPID; queue->state.motion_type = command->segment.motion_type;
desired_velocity = planned_velocity(queue, 0);
acceleration = (desired_velocity - meta->current_velocity) / queue->cycle_time;
if (acceleration > meta->current_acceleration + meta->jerk_limit * queue->cycle_time) acceleration = meta->current_acceleration + meta->jerk_limit * queue->cycle_time;

View File

@@ -60,7 +60,7 @@ int main(void) {
assert(override_state.position.tran.x > 0.049 && override_state.position.tran.x < 0.051);
assert(override_state.velocity > 0.49 && override_state.velocity < 0.51);
sim_motion_reset(&override_queue);
override_command.flags = SIM_MOTION_COMMAND_FLAG_RAPID;
override_command.tag = SIM_MOTION_COMMAND_TAG_RAPID;
assert(sim_motion_enqueue(&override_queue, &override_command, 0) == SIM_MOTION_OK);
assert(sim_motion_step(&override_queue) == SIM_MOTION_OK);
assert(sim_motion_read_state(&override_queue, &override_state) == SIM_MOTION_OK);

View File

@@ -102,10 +102,10 @@ export class WasmMotionQueue {
[...poseToArray(segment.start), ...poseToArray(segment.end), Number(segment.center?.x ?? 0), Number(segment.center?.y ?? 0), Number(segment.center?.z ?? 0), Number(segment.normal?.x ?? 0), Number(segment.normal?.y ?? 0), Number(segment.normal?.z ?? 0), Number(segment.velocity ?? 0), Number(segment.acceleration ?? 0)].forEach((value, index) => { doubles[base + index] = value; });
ints[this.command / 4 + SEGMENT_INT_OFFSET] = Number(segment.motion_type ?? 1);
ints[this.command / 4 + SEGMENT_INT_OFFSET + 1] = Number(segment.turn ?? 0);
// sim_motion_command layout is segment (216 bytes), id (4), tag (4), flags (4).
// sim_motion_command layout is segment (216 bytes), id (4), tag (4).
// Keep the WASM switchkins mode in the tag field; the C queue assigns id.
ints[this.command / 4 + SEGMENT_INT_OFFSET + 3] = Number(segment.kinematics_mode ?? segment.tag ?? 0);
ints[this.command / 4 + SEGMENT_INT_OFFSET + 4] = segment.kind === "rapid" ? 1 : 0;
const tag = Number(segment.kinematics_mode ?? segment.tag ?? 0) & 0x7fffffff;
ints[this.command / 4 + SEGMENT_INT_OFFSET + 3] = tag | (segment.kind === "rapid" ? 0x80000000 : 0);
const result = call(this.core, "sim_motion_enqueue", "number", ["number", "number", "number"], [this.queue, this.command, 0]);
return result === 0 ? { status: "verified", source_line: segment.source_line ?? null } : { status: "error", code: `wasm_motion_enqueue_${result}`, reason: MOTION_ERROR_REASONS[result] ?? `wasm_motion_enqueue_${result}`, message_key: MOTION_ERROR_REASONS[result] ?? `wasm_motion_enqueue_${result}`, source: "linuxcnc-wasm-motion" };
}