Complete 3axis tutorial native and Web/WASM parity tools

This commit is contained in:
2026-08-24 14:01:30 +08:00
parent 938654b19d
commit 7e90142b63
147 changed files with 17639 additions and 557 deletions

View File

@@ -31,6 +31,8 @@ typedef struct interpreter_meta {
int coolant_mode;
int selected_tool;
double tool_length;
sim_posemath_segment last_motion;
int has_motion;
uint32_t error_column;
int32_t error_code;
} interpreter_meta;
@@ -410,13 +412,14 @@ int sim_interpreter_reset(sim_interpreter *interpreter) {
int sim_interpreter_init(sim_interpreter *interpreter) { return sim_interpreter_reset(interpreter); }
int sim_interpreter_execute(sim_interpreter *interpreter, const char *block, uint32_t length) {
sim_interpreter_state next; interpreter_meta *meta; expression_parser parser; const char *end;
sim_interpreter_state previous; sim_interpreter_state next; interpreter_meta *meta; expression_parser parser; const char *end;
int groups[6] = {0}, seen_axis[9] = {0}, seen_feed = 0, seen_speed = 0, seen_line = 0, seen_p = 0, seen_r = 0, seen_g10 = 0, result = SIM_INTERP_OK;
double axis_values[9] = {0}, feed_value = 0.0, speed_value = 0.0, p_value = 0.0, r_value = 0.0;
int seen_center[3] = {0};
double axis_values[9] = {0}, center_values[3] = {0}, feed_value = 0.0, speed_value = 0.0, p_value = 0.0, r_value = 0.0;
if (interpreter == NULL || block == NULL || length == 0) return SIM_INTERP_ERR_ARGUMENT;
meta = meta_for(interpreter, 1); if (meta == NULL || !finite_state(&interpreter->state)) return SIM_INTERP_ERR_STATE;
if (interpreter->state.program_end) { set_error(interpreter, meta, SIM_INTERP_ERR_STATE, 1); return SIM_INTERP_ERR_STATE; }
next = interpreter->state; parser.meta = meta; parser.cursor = block; parser.end = block + length; parser.pending_count = 0; end = parser.end;
previous = interpreter->state; next = interpreter->state; meta->has_motion = 0; parser.meta = meta; parser.cursor = block; parser.end = block + length; parser.pending_count = 0; end = parser.end;
while (parser.cursor < end) {
char letter; double value; int index; uint32_t column;
while (parser.cursor < end && isspace((unsigned char)*parser.cursor)) ++parser.cursor;
@@ -453,7 +456,13 @@ int sim_interpreter_execute(sim_interpreter *interpreter, const char *block, uin
case 'N': if (seen_line++) result = SIM_INTERP_ERR_STATE; else if (value < 0.0 || value > 4294967295.0 || floor(value) != value) result = SIM_INTERP_ERR_RANGE; else next.line = (uint32_t)value; break;
case 'F': if (seen_feed++) result = SIM_INTERP_ERR_STATE; else if (value < 0.0) result = SIM_INTERP_ERR_RANGE; else feed_value = value; break;
case 'S': if (seen_speed++) result = SIM_INTERP_ERR_STATE; else if (value < 0.0) result = SIM_INTERP_ERR_RANGE; else speed_value = value; break;
case 'I': case 'J': case 'K': case 'L': case 'Q': case 'D': case 'E': break;
case 'I': case 'J': case 'K': {
int center_index = letter == 'I' ? 0 : letter == 'J' ? 1 : 2;
if (seen_center[center_index]++) result = SIM_INTERP_ERR_STATE;
else center_values[center_index] = value;
break;
}
case 'L': case 'Q': case 'D': case 'E': break;
case 'P': if (seen_p++) result = SIM_INTERP_ERR_STATE; else p_value = value; break;
case 'R': if (seen_r++) result = SIM_INTERP_ERR_STATE; else r_value = value; break;
case 'T': if (value < 0.0 || value > 1001.0 || floor(value) != value) result = SIM_INTERP_ERR_RANGE; else meta->selected_tool = (int)value; break;
@@ -488,6 +497,33 @@ int sim_interpreter_execute(sim_interpreter *interpreter, const char *block, uin
if (meta->tool_length != 0.0 && meta->cutter_comp == 43 && seen_axis[2]) next.z -= meta->tool_length;
if (!finite_state(&next)) { set_error(interpreter, meta, SIM_INTERP_ERR_NONFINITE, 1); return SIM_INTERP_ERR_NONFINITE; }
if (!seen_line) next.line = interpreter->state.line + 1u; next.status = SIM_INTERP_OK; interpreter->state = next;
{
size_t axis;
int has_axis_motion = 0;
int has_center = seen_center[0] || seen_center[1] || seen_center[2];
for (axis = 0; axis < 9; ++axis) if (seen_axis[axis]) { has_axis_motion = 1; break; }
if ((has_axis_motion || has_center) && next.motion_mode >= 0 && next.motion_mode <= 3) {
sim_posemath_segment *segment = &meta->last_motion;
memset(segment, 0, sizeof(*segment));
segment->start.tran.x = previous.x; segment->start.tran.y = previous.y; segment->start.tran.z = previous.z;
segment->start.a = previous.a; segment->start.b = previous.b; segment->start.c = previous.c;
segment->start.u = previous.u; segment->start.v = previous.v; segment->start.w = previous.w;
segment->end.tran.x = next.x; segment->end.tran.y = next.y; segment->end.tran.z = next.z;
segment->end.a = next.a; segment->end.b = next.b; segment->end.c = next.c;
segment->end.u = next.u; segment->end.v = next.v; segment->end.w = next.w;
segment->velocity = next.feed;
segment->acceleration = 0.0;
segment->motion_type = next.motion_mode >= 2 ? SIM_POSEMATH_CIRCULAR : SIM_POSEMATH_LINEAR;
segment->turn = next.motion_mode == 2 ? -1 : 1;
segment->center.x = previous.x; segment->center.y = previous.y; segment->center.z = previous.z;
if (next.units == SIM_INTERP_UNITS_INCH) for (axis = 0; axis < 3; ++axis) center_values[axis] *= 25.4;
segment->center.x += center_values[0]; segment->center.y += center_values[1]; segment->center.z += center_values[2];
if (next.plane == 18) segment->normal.y = 1.0;
else if (next.plane == 19) segment->normal.x = 1.0;
else segment->normal.z = 1.0;
meta->has_motion = 1;
}
}
{
size_t item; for (item = 0; item < parser.pending_count; ++item) meta->parameters[parser.pending_index[item]] = parser.pending_value[item];
}
@@ -498,6 +534,16 @@ int sim_interpreter_execute(sim_interpreter *interpreter, const char *block, uin
int sim_interpreter_read_state(const sim_interpreter *interpreter, sim_interpreter_state *state) { if (interpreter == NULL || state == NULL) return SIM_INTERP_ERR_ARGUMENT; *state = interpreter->state; return SIM_INTERP_OK; }
int sim_interpreter_read_motion(const sim_interpreter *interpreter, sim_posemath_segment *segment) {
interpreter_meta *meta = meta_for(interpreter, 0);
if (meta == NULL || segment == NULL) return SIM_INTERP_ERR_ARGUMENT;
if (!meta->has_motion) return SIM_INTERP_ERR_STATE;
*segment = meta->last_motion;
return SIM_INTERP_OK;
}
uint32_t sim_interpreter_motion_size(void) { return (uint32_t)sizeof(sim_posemath_segment); }
uint32_t sim_interpreter_canonical(const sim_interpreter *interpreter, char *output, uint32_t capacity) {
if (interpreter == NULL) return 0; if (output == NULL || capacity == 0) return interpreter->canonical_length + 1u; if (capacity <= interpreter->canonical_length) return interpreter->canonical_length + 1u; memcpy(output, interpreter->canonical, interpreter->canonical_length + 1u); return interpreter->canonical_length + 1u;
}

View File

@@ -54,6 +54,27 @@ static double segment_length(const sim_posemath_segment *segment) {
const double dy = segment->end.tran.y - segment->start.tran.y;
const double dz = segment->end.tran.z - segment->start.tran.z;
double value = dx * dx + dy * dy + dz * dz;
if (segment->motion_type == SIM_POSEMATH_CIRCULAR) {
const double sx = segment->start.tran.x - segment->center.x;
const double sy = segment->start.tran.y - segment->center.y;
const double sz = segment->start.tran.z - segment->center.z;
const double ex = segment->end.tran.x - segment->center.x;
const double ey = segment->end.tran.y - segment->center.y;
const double ez = segment->end.tran.z - segment->center.z;
const double radius = sqrt(sx * sx + sy * sy + sz * sz);
const double dot = sx * ex + sy * ey + sz * ez;
const double cross_x = sy * ez - sz * ey;
const double cross_y = sz * ex - sx * ez;
const double cross_z = sx * ey - sy * ex;
const double normal_length = sqrt(segment->normal.x * segment->normal.x + segment->normal.y * segment->normal.y + segment->normal.z * segment->normal.z);
double angle;
if (!isfinite(radius) || radius <= 1e-12 || !isfinite(normal_length) || normal_length <= 1e-12) return 0.0;
angle = atan2((segment->normal.x * cross_x + segment->normal.y * cross_y + segment->normal.z * cross_z) / normal_length, dot);
if (angle < 0.0) angle = -angle;
if (angle <= 1e-12) angle = 2.0 * M_PI;
if (segment->turn > 1 || segment->turn < -1) angle += 2.0 * M_PI * (fabs((double)segment->turn) - 1.0);
return isfinite(radius * angle) && radius * angle > 0.0 ? radius * angle : 0.0;
}
return isfinite(value) && value > 0.0 ? sqrt(value) : 0.0;
}
@@ -94,6 +115,10 @@ int sim_motion_init(sim_motion_queue *queue, double cycle_time, double velocity_
return sim_motion_reset(queue);
}
uint32_t sim_motion_size(void) { return (uint32_t)sizeof(sim_motion_queue); }
uint32_t sim_motion_command_size(void) { return (uint32_t)sizeof(sim_motion_command); }
uint32_t sim_motion_state_size(void) { return (uint32_t)sizeof(sim_motion_state); }
int sim_motion_set_profile(sim_motion_queue *queue, int profile) {
motion_meta *meta = meta_for(queue, 1);
if (meta == NULL || (profile != SIM_MOTION_PROFILE_BLEND && profile != SIM_MOTION_PROFILE_EXACT_STOP)) return SIM_MOTION_ERR_ARGUMENT;
@@ -120,6 +145,11 @@ int sim_motion_set_paused(sim_motion_queue *queue, uint32_t paused) {
motion_meta *meta = meta_for(queue, 1);
if (meta == NULL || paused > 1u) return SIM_MOTION_ERR_ARGUMENT;
meta->paused = paused;
if (paused != 0u) {
meta->current_velocity = 0.0;
meta->current_acceleration = 0.0;
queue->state.velocity = 0.0;
}
return SIM_MOTION_OK;
}

View File

@@ -118,7 +118,7 @@ int sim_posemath_segment_validate(const sim_posemath_segment *segment) {
length_sq = (segment->end.tran.x - segment->start.tran.x) * (segment->end.tran.x - segment->start.tran.x) +
(segment->end.tran.y - segment->start.tran.y) * (segment->end.tran.y - segment->start.tran.y) +
(segment->end.tran.z - segment->start.tran.z) * (segment->end.tran.z - segment->start.tran.z);
if (!isfinite(length_sq) || length_sq <= 1e-24) return SIM_POSEMATH_ERR_DEGENERATE;
if (!isfinite(length_sq) || (length_sq <= 1e-24 && segment->motion_type != SIM_POSEMATH_CIRCULAR)) return SIM_POSEMATH_ERR_DEGENERATE;
if (segment->motion_type == SIM_POSEMATH_CIRCULAR) {
normal_sq = segment->normal.x * segment->normal.x + segment->normal.y * segment->normal.y + segment->normal.z * segment->normal.z;
if (!isfinite(normal_sq) || normal_sq <= 1e-24) return SIM_POSEMATH_ERR_DEGENERATE;