diff --git a/README.zh-CN.md b/README.zh-CN.md index d510bdf..32521dc 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -58,6 +58,7 @@ The first useful target is: - 已有 LinuxCNC RS274 源码级链接 smoke:本项目直接编译 23 个解释器 core 源文件,不再通过 `librs274` 取得解释器主体。 - 已有五轴 RTCP 第一版几何内核,可根据编程刀尖点、A/B/C 姿态和刀长计算枢轴/主轴点补偿位置。 - 已有坐标系事件回归语料,覆盖 `G10 L2`、`G10 L20` 的 G5X/XY 旋转事件和 `G92.1` 清零事件。 +- 已有探针事件回归语料,LinuxCNC `G38.3` 会输出独立 `probe` 事件,不再混作普通直线进给。 - LinuxCNC Canon bridge 会把当前解释行号补到没有自带 `lineno` 的回调事件上,方便 Web 端诊断和源码高亮。 - 下一步是继续替换源码级链接中残留的 Python、INI/HAL、文件系统和动态加载依赖,并把 RTCP 内核接入 canon 事件流和机型配置。 @@ -78,6 +79,7 @@ The first useful target is: - LinuxCNC RS274 源码级链接 smoke - 五轴 RTCP 几何内核 smoke - `G10 L2` / `G10 L20` / `G92.1` 坐标系事件回归 +- `G38.3` 探针事件回归 ## 后端选择 diff --git a/core/src/canon_event_sink.cpp b/core/src/canon_event_sink.cpp index 1da1f04..40ad5a3 100644 --- a/core/src/canon_event_sink.cpp +++ b/core/src/canon_event_sink.cpp @@ -156,6 +156,14 @@ void CanonEventSink::arc_feed(int line, const CncSimPose &end, const CncSimPose position_ = end; } +void CanonEventSink::straight_probe(int line, const CncSimPose &end) { + CncSimEvent event = base_event(CNC_SIM_EVENT_PROBE, line); + event.start = position_; + event.end = end; + emit(event); + position_ = end; +} + void CanonEventSink::dwell(double seconds, int line) { CncSimEvent event = base_event(CNC_SIM_EVENT_DWELL, line); event.dwell_seconds = seconds; diff --git a/core/src/canon_event_sink.h b/core/src/canon_event_sink.h index ef205c9..659a777 100644 --- a/core/src/canon_event_sink.h +++ b/core/src/canon_event_sink.h @@ -27,6 +27,7 @@ public: void straight_traverse(int line, const CncSimPose &end); void straight_feed(int line, const CncSimPose &end); void arc_feed(int line, const CncSimPose &end, const CncSimPose ¢er, int turns); + void straight_probe(int line, const CncSimPose &end); void dwell(double seconds, int line); void program_end(int line); void emit_raw(CncSimEvent event); diff --git a/core/src/linuxcnc_canon_bridge.cpp b/core/src/linuxcnc_canon_bridge.cpp index 9cc0fbb..d730905 100644 --- a/core/src/linuxcnc_canon_bridge.cpp +++ b/core/src/linuxcnc_canon_bridge.cpp @@ -341,7 +341,7 @@ void STRAIGHT_PROBE(int lineno, double u, double v, double w, unsigned char) { if (active_sink) { - active_sink->straight_feed(lineno, make_pose(x, y, z, a, b, c, u, v, w)); + active_sink->straight_probe(event_line(lineno), make_pose(x, y, z, a, b, c, u, v, w)); } } diff --git a/core/tests/cnc_sim_api_linuxcnc_rs274_smoke.cpp b/core/tests/cnc_sim_api_linuxcnc_rs274_smoke.cpp index 31bb717..41c4165 100644 --- a/core/tests/cnc_sim_api_linuxcnc_rs274_smoke.cpp +++ b/core/tests/cnc_sim_api_linuxcnc_rs274_smoke.cpp @@ -71,6 +71,8 @@ int main() { bool saw_coordinate_end_line = false; bool saw_l20_g55_offset = false; bool saw_l20_end_line = false; + bool saw_probe = false; + bool saw_probe_as_feed = false; for (const auto &event : events) { saw_tool = saw_tool || event.type == CNC_SIM_EVENT_TOOL_CHANGE; saw_rapid = saw_rapid || event.type == CNC_SIM_EVENT_RAPID; @@ -119,6 +121,29 @@ int main() { ok &= expect(saw_g49, "expected LinuxCNC G49 RTCP off state"); ok &= expect(saw_g434, "expected LinuxCNC G43.4 RTCP on state with H code"); + const char probe_program[] = + "G21 G90 G17\n" + "G0 X0 Y0 Z5\n" + "F100\n" + "G38.3 Z0\n" + "M30\n"; + events.clear(); + ok &= expect(cnc_sim_parse_program(sim, probe_program, sizeof(probe_program) - 1) == 0, + cnc_sim_last_error(sim)); + for (const auto &event : events) { + saw_probe = saw_probe || + (event.type == CNC_SIM_EVENT_PROBE && + event.line == 4 && + event.feed == 100.0 && + event.start.z == 5.0 && + event.end.z == 0.0); + saw_probe_as_feed = saw_probe_as_feed || + (event.type == CNC_SIM_EVENT_LINEAR_FEED && + event.line == 4); + } + ok &= expect(saw_probe, "expected LinuxCNC G38.3 probe event"); + ok &= expect(!saw_probe_as_feed, "expected LinuxCNC G38.3 to avoid linear-feed event"); + const char l20_program[] = "G21 G90 G17\n" "G0 X5 Y6 Z7\n" diff --git a/core/tests/linuxcnc_canon_bridge_smoke.cpp b/core/tests/linuxcnc_canon_bridge_smoke.cpp index c2ad052..aceede8 100644 --- a/core/tests/linuxcnc_canon_bridge_smoke.cpp +++ b/core/tests/linuxcnc_canon_bridge_smoke.cpp @@ -39,6 +39,7 @@ int main() { STRAIGHT_TRAVERSE(10, 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); STRAIGHT_FEED(11, 10.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); ARC_FEED(12, 10.0, 10.0, 10.0, 5.0, 1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); + STRAIGHT_PROBE(13, 10.0, 10.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0); SET_G5X_OFFSET(1, 10.0, 20.0, 30.0, 1.0, 2.0, 3.0, 0.0, 0.0, 0.0); SET_G92_OFFSET(1.0, 2.0, 3.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); SET_XY_ROTATION(15.0); @@ -53,6 +54,7 @@ int main() { bool saw_rapid = false; bool saw_feed = false; bool saw_arc = false; + bool saw_probe = false; bool saw_g5x = false; bool saw_g92 = false; bool saw_rotation = false; @@ -65,6 +67,11 @@ int main() { event.end.y == 10.0 && event.center.x == 10.0 && event.center.y == 5.0); + saw_probe = saw_probe || (event.type == CNC_SIM_EVENT_PROBE && + event.line == 13 && + event.start.x == 10.0 && + event.start.y == 10.0 && + event.end.z == -1.0); saw_g5x = saw_g5x || (event.type == CNC_SIM_EVENT_SET_G5X_OFFSET && event.tool == 1 && event.start.x == 10.0 && @@ -86,6 +93,7 @@ int main() { ok &= expect(saw_rapid, "expected rapid move"); ok &= expect(saw_feed, "expected linear feed"); ok &= expect(saw_arc, "expected arc feed"); + ok &= expect(saw_probe, "expected probe event"); ok &= expect(saw_g5x, "expected G5X offset event"); ok &= expect(saw_g92, "expected G92 offset event"); ok &= expect(saw_rotation, "expected XY rotation event"); diff --git a/test-linuxcnc-rs274-native.sh b/test-linuxcnc-rs274-native.sh index ce2df3c..d97a65c 100755 --- a/test-linuxcnc-rs274-native.sh +++ b/test-linuxcnc-rs274-native.sh @@ -38,6 +38,7 @@ CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linux CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/basic_mill.ngc >/tmp/cnc_sim_linuxcnc_basic_mill.json CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_rtcp_controls.ngc >/tmp/cnc_sim_linuxcnc_rtcp_controls.json CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_canned_cycle.ngc >/tmp/cnc_sim_linuxcnc_canned_cycle.json +CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_probe_no_error.ngc >/tmp/cnc_sim_linuxcnc_probe_no_error.json cp "$base_var_file" "$var_file" CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_coordinate_offsets.ngc >/tmp/cnc_sim_linuxcnc_coordinate_offsets.json cp "$base_var_file" "$var_file" @@ -82,6 +83,19 @@ actual_cycle = [(event["type"], event["end"]["x"], event["end"]["y"], event["end if actual_cycle != expected_cycle: raise SystemExit(f"unexpected G81/G80 expansion: {actual_cycle!r}") +probe = json.loads(Path("/tmp/cnc_sim_linuxcnc_probe_no_error.json").read_text()) +if not any( + event["type"] == "probe" and + event["line"] == 4 and + event["feed"] == 100 and + event["start"]["z"] == 5 and + event["end"]["z"] == 0 + for event in probe +): + raise SystemExit("missing G38.3 probe event") +if any(event["type"] == "linear-feed" and event["line"] == 4 for event in probe): + raise SystemExit("G38.3 probe should not be emitted as linear-feed") + coords = json.loads(Path("/tmp/cnc_sim_linuxcnc_coordinate_offsets.json").read_text()) g5x = [event for event in coords if event["type"] == "set-g5x-offset"] g92 = [event for event in coords if event["type"] == "set-g92-offset"] @@ -128,5 +142,6 @@ echo "dumped /tmp/cnc_sim_linuxcnc_basic_motion.json" echo "dumped /tmp/cnc_sim_linuxcnc_basic_mill.json" echo "dumped /tmp/cnc_sim_linuxcnc_rtcp_controls.json" echo "dumped /tmp/cnc_sim_linuxcnc_canned_cycle.json" +echo "dumped /tmp/cnc_sim_linuxcnc_probe_no_error.json" echo "dumped /tmp/cnc_sim_linuxcnc_coordinate_offsets.json" echo "dumped /tmp/cnc_sim_linuxcnc_coordinate_l20.json" diff --git a/tests/gcode/linuxcnc_probe_no_error.ngc b/tests/gcode/linuxcnc_probe_no_error.ngc new file mode 100644 index 0000000..83d8476 --- /dev/null +++ b/tests/gcode/linuxcnc_probe_no_error.ngc @@ -0,0 +1,5 @@ +G21 G90 G17 +G0 X0 Y0 Z5 +F100 +G38.3 Z0 +M30