diff --git a/README.zh-CN.md b/README.zh-CN.md index ba9d92a..23266c8 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -65,6 +65,7 @@ The first useful target is: - 已有停止类事件回归语料,`M0/M1/M60` 会通过 `program-end.reserved` 输出 `1=程序停`、`2=可选停`、`3=托盘交换`。 - 已有冷却液状态回归语料,`M7/M8/M9` 会通过 `comment.reserved` 临时输出 `10/11=mist off/on`、`20/21=flood off/on`。 - 已有进给模式回归语料,`G93/G94/G95` 会通过 `comment.reserved` 临时输出 `93/94/95`,并通过 `set-feed` 记录 Canon feed mode 回调。 +- 已有运动控制模式回归语料,`G61/G61.1/G64` 会通过 `comment.reserved` 临时输出 `611/612/640`,`feed` 暂存 G64 tolerance。 - LinuxCNC Canon bridge 会把当前解释行号补到没有自带 `lineno` 的回调事件上,方便 Web 端诊断和源码高亮。 - 下一步是继续替换源码级链接中残留的 Python、INI/HAL、文件系统和动态加载依赖,并把 RTCP 内核接入 canon 事件流和机型配置。 @@ -90,6 +91,7 @@ The first useful target is: - `M0` / `M1` / `M60` 停止类事件回归 - `M7` / `M8` / `M9` 冷却液状态回归 - `G93` / `G94` / `G95` 进给模式回归 +- `G61` / `G61.1` / `G64` 运动控制模式回归 - `G10 L2` / `G10 L20` / `G92.1` 坐标系事件回归 - `G38.3` 探针事件回归 diff --git a/core/src/linuxcnc_canon_bridge.cpp b/core/src/linuxcnc_canon_bridge.cpp index 067c7ec..b4cd7f2 100644 --- a/core/src/linuxcnc_canon_bridge.cpp +++ b/core/src/linuxcnc_canon_bridge.cpp @@ -302,7 +302,31 @@ void SET_FEED_MODE(int, int) { } } -void SET_MOTION_CONTROL_MODE(CANON_MOTION_MODE, double) { +void SET_MOTION_CONTROL_MODE(CANON_MOTION_MODE mode, double tolerance) { + int reserved = 0; + switch (mode) { + case CANON_EXACT_PATH: + reserved = 611; + break; + case CANON_EXACT_STOP: + reserved = 612; + break; + case CANON_CONTINUOUS: + reserved = 640; + break; + default: + reserved = 0; + break; + } + if (active_sink) { + CncSimEvent event{}; + event.version = 1; + event.type = CNC_SIM_EVENT_COMMENT; + event.line = event_line(); + event.feed = tolerance; + event.reserved = reserved; + active_sink->emit_raw(event); + } } void SET_NAIVECAM_TOLERANCE(double) { diff --git a/core/src/smoke_gcode_parser.cpp b/core/src/smoke_gcode_parser.cpp index 345e1cd..c04876e 100644 --- a/core/src/smoke_gcode_parser.cpp +++ b/core/src/smoke_gcode_parser.cpp @@ -323,6 +323,22 @@ int SmokeGcodeParser::parse(const char *program, size_t program_len, std::string if (stop_if_callback_aborted(sink_, error)) { return -1; } + } else if (g == 61) { + emit_comment_state(sink_, line_number, g_code_is(word.value, 61.1) ? 612 : 611); + if (stop_if_callback_aborted(sink_, error)) { + return -1; + } + } else if (g == 64) { + CncSimEvent event{}; + event.version = 1; + event.type = CNC_SIM_EVENT_COMMENT; + event.line = line_number; + event.feed = words.count('P') ? words.at('P') : 0.0; + event.reserved = 640; + sink_.emit_raw(event); + if (stop_if_callback_aborted(sink_, error)) { + return -1; + } } else if (g == 0 || g == 1 || g == 2 || g == 3) { modal_motion = g; } else if (g == 4) { diff --git a/core/tests/cnc_sim_api_linuxcnc_rs274_smoke.cpp b/core/tests/cnc_sim_api_linuxcnc_rs274_smoke.cpp index 0f0bf2c..5ede830 100644 --- a/core/tests/cnc_sim_api_linuxcnc_rs274_smoke.cpp +++ b/core/tests/cnc_sim_api_linuxcnc_rs274_smoke.cpp @@ -91,6 +91,9 @@ int main() { bool saw_g95_mode = false; bool saw_g94_feed_mode = false; bool saw_g95_feed_mode = false; + bool saw_g61_mode = false; + bool saw_g611_mode = false; + bool saw_g64_mode = 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; @@ -285,6 +288,34 @@ int main() { ok &= expect(saw_g94_feed_mode, "expected LinuxCNC G94 set-feed mode event"); ok &= expect(saw_g95_feed_mode, "expected LinuxCNC G95 set-feed mode event"); + const char motion_mode_program[] = + "G21 G90 G17\n" + "G61\n" + "G61.1\n" + "G64 P0.05\n" + "M30\n"; + events.clear(); + ok &= expect(cnc_sim_parse_program(sim, motion_mode_program, sizeof(motion_mode_program) - 1) == 0, + cnc_sim_last_error(sim)); + for (const auto &event : events) { + saw_g61_mode = saw_g61_mode || + (event.type == CNC_SIM_EVENT_COMMENT && + event.line == 2 && + event.reserved == 611); + saw_g611_mode = saw_g611_mode || + (event.type == CNC_SIM_EVENT_COMMENT && + event.line == 3 && + event.reserved == 612); + saw_g64_mode = saw_g64_mode || + (event.type == CNC_SIM_EVENT_COMMENT && + event.line == 4 && + event.reserved == 640 && + event.feed == 0.05); + } + ok &= expect(saw_g61_mode, "expected LinuxCNC G61 exact path mode"); + ok &= expect(saw_g611_mode, "expected LinuxCNC G61.1 exact stop mode"); + ok &= expect(saw_g64_mode, "expected LinuxCNC G64 continuous mode"); + const char comment_program[] = "G21 G90 G17\n" "(operator note)\n" diff --git a/core/tests/cnc_sim_api_smoke.cpp b/core/tests/cnc_sim_api_smoke.cpp index 73bdc09..7143d13 100644 --- a/core/tests/cnc_sim_api_smoke.cpp +++ b/core/tests/cnc_sim_api_smoke.cpp @@ -81,6 +81,9 @@ int main() { bool saw_g94_mode = false; bool saw_g95_mode = false; bool saw_g95_feed_mode = false; + bool saw_g61_mode = false; + bool saw_g611_mode = false; + bool saw_g64_mode = false; bool saw_incremental_move = false; bool saw_r_arc_center = false; for (const auto &event : events) { @@ -261,6 +264,33 @@ int main() { ok &= expect(saw_g95_mode, "expected G95 feed mode state"); ok &= expect(saw_g95_feed_mode, "expected G95 feed-per-rev set-feed mode"); + const char motion_mode_program[] = + "G21\n" + "G61\n" + "G61.1\n" + "G64 P0.05\n"; + events.clear(); + ok &= expect(cnc_sim_parse_program(sim, motion_mode_program, sizeof(motion_mode_program) - 1) == 0, + cnc_sim_last_error(sim)); + for (const auto &event : events) { + saw_g61_mode = saw_g61_mode || + (event.type == CNC_SIM_EVENT_COMMENT && + event.line == 2 && + event.reserved == 611); + saw_g611_mode = saw_g611_mode || + (event.type == CNC_SIM_EVENT_COMMENT && + event.line == 3 && + event.reserved == 612); + saw_g64_mode = saw_g64_mode || + (event.type == CNC_SIM_EVENT_COMMENT && + event.line == 4 && + event.reserved == 640 && + event.feed == 0.05); + } + ok &= expect(saw_g61_mode, "expected G61 exact path mode"); + ok &= expect(saw_g611_mode, "expected G61.1 exact stop mode"); + ok &= expect(saw_g64_mode, "expected G64 continuous mode"); + const char linuxcnc_config[] = "{\"backend\":\"linuxcnc-rs274\"}"; config_rc = cnc_sim_load_config_json(sim, linuxcnc_config, sizeof(linuxcnc_config) - 1); rc = cnc_sim_parse_program(sim, program, sizeof(program) - 1); diff --git a/test-linuxcnc-rs274-native.sh b/test-linuxcnc-rs274-native.sh index 6f2bf4b..8919ada 100755 --- a/test-linuxcnc-rs274-native.sh +++ b/test-linuxcnc-rs274-native.sh @@ -42,6 +42,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/linuxcnc_program_stops.ngc >/tmp/cnc_sim_linuxcnc_program_stops.json CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_coolant.ngc >/tmp/cnc_sim_linuxcnc_coolant.json CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_feed_modes.ngc >/tmp/cnc_sim_linuxcnc_feed_modes.json +CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_motion_modes.ngc >/tmp/cnc_sim_linuxcnc_motion_modes.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_comments.ngc >/tmp/cnc_sim_linuxcnc_comments.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 @@ -136,6 +137,16 @@ for expected in [(3, 0), (4, 0)]: if expected not in feed_mode_events: raise SystemExit(f"missing feed mode event {expected!r}") +motion_modes = json.loads(Path("/tmp/cnc_sim_linuxcnc_motion_modes.json").read_text()) +motion_mode_states = [ + (event["line"], event["reserved"], event["feed"]) + for event in motion_modes + if event["type"] == "comment" +] +for expected in [(2, 611, 0), (3, 612, 0), (4, 640, 0.05)]: + if expected not in motion_mode_states: + raise SystemExit(f"missing motion mode state {expected!r}") + cycle = json.loads(Path("/tmp/cnc_sim_linuxcnc_canned_cycle.json").read_text()) motions = [event for event in cycle if event["type"] in {"rapid", "linear-feed"}] expected_cycle = [ @@ -216,6 +227,7 @@ echo "dumped /tmp/cnc_sim_linuxcnc_tool_number.json" echo "dumped /tmp/cnc_sim_linuxcnc_program_stops.json" echo "dumped /tmp/cnc_sim_linuxcnc_coolant.json" echo "dumped /tmp/cnc_sim_linuxcnc_feed_modes.json" +echo "dumped /tmp/cnc_sim_linuxcnc_motion_modes.json" echo "dumped /tmp/cnc_sim_linuxcnc_canned_cycle.json" echo "dumped /tmp/cnc_sim_linuxcnc_comments.json" echo "dumped /tmp/cnc_sim_linuxcnc_probe_no_error.json" diff --git a/tests/gcode/linuxcnc_motion_modes.ngc b/tests/gcode/linuxcnc_motion_modes.ngc new file mode 100644 index 0000000..9ec34bc --- /dev/null +++ b/tests/gcode/linuxcnc_motion_modes.ngc @@ -0,0 +1,5 @@ +G21 G90 G17 +G61 +G61.1 +G64 P0.05 +M30