From ccd51ff3730093ff70dc5b619c606388a236294c Mon Sep 17 00:00:00 2001 From: cnc Date: Sat, 6 Jun 2026 08:15:59 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8C=89=E6=BA=90=E5=90=8C=E6=AD=A5=E5=8D=95?= =?UTF-8?q?=E4=BD=8D=E5=88=87=E6=8D=A2=E5=BD=93=E5=89=8D=E4=BD=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 结论:依据 LinuxCNC interp_convert.cc convert_length_units 与 unit_tests/interp/test_interp_basics.cc,G20/G21 切换时事件桥同步重标定当前线性坐标,native/source-link 覆盖通过。 --- core/src/canon_event_sink.cpp | 35 +++++++++++++++++++ core/src/canon_event_sink.h | 1 + core/src/linuxcnc_canon_bridge.cpp | 2 +- test-linuxcnc-rs274-native.sh | 26 ++++++++++++++ test-linuxcnc-source-link.sh | 28 +++++++++++++++ .../gcode/linuxcnc_units_current_position.ngc | 8 +++++ 6 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 tests/gcode/linuxcnc_units_current_position.ngc diff --git a/core/src/canon_event_sink.cpp b/core/src/canon_event_sink.cpp index ed1a324..19c26da 100644 --- a/core/src/canon_event_sink.cpp +++ b/core/src/canon_event_sink.cpp @@ -234,6 +234,41 @@ void CanonEventSink::set_xy_rotation(double angle_degrees, int line) { } void CanonEventSink::use_length_units(double scale, int line) { + use_length_units(scale, line, false); +} + +void CanonEventSink::use_length_units(double scale, int line, bool rescale_linear_state) { + if (rescale_linear_state && unit_scale_ != 0.0 && scale != unit_scale_) { + const double factor = unit_scale_ / scale; + // LinuxCNC src/emc/rs274ngc/interp_convert.cc convert_length_units() + // rescales linear current axes on G20/G21; A/B/C remain angular. + position_.x *= factor; + position_.y *= factor; + position_.z *= factor; + position_.u *= factor; + position_.v *= factor; + position_.w *= factor; + tool_length_offset_.x *= factor; + tool_length_offset_.y *= factor; + tool_length_offset_.z *= factor; + tool_length_offset_.u *= factor; + tool_length_offset_.v *= factor; + tool_length_offset_.w *= factor; + probe_position_.x *= factor; + probe_position_.y *= factor; + probe_position_.z *= factor; + probe_position_.u *= factor; + probe_position_.v *= factor; + probe_position_.w *= factor; + if (has_pending_motion_start_) { + pending_motion_start_.x *= factor; + pending_motion_start_.y *= factor; + pending_motion_start_.z *= factor; + pending_motion_start_.u *= factor; + pending_motion_start_.v *= factor; + pending_motion_start_.w *= factor; + } + } unit_scale_ = scale; CncSimEvent event = base_event(CNC_SIM_EVENT_SET_UNITS, line); event.feed = scale; diff --git a/core/src/canon_event_sink.h b/core/src/canon_event_sink.h index 6271530..d390ac6 100644 --- a/core/src/canon_event_sink.h +++ b/core/src/canon_event_sink.h @@ -29,6 +29,7 @@ public: void set_xy_rotation(double angle_degrees, int line); void use_length_units(double scale, int line); + void use_length_units(double scale, int line, bool rescale_linear_state); void select_plane(int plane, int line); void set_traverse_rate(double rate); void set_feed_rate(double feed, int line); diff --git a/core/src/linuxcnc_canon_bridge.cpp b/core/src/linuxcnc_canon_bridge.cpp index 0b30838..f4e2dea 100644 --- a/core/src/linuxcnc_canon_bridge.cpp +++ b/core/src/linuxcnc_canon_bridge.cpp @@ -193,7 +193,7 @@ void INIT_CANON() { void USE_LENGTH_UNITS(CANON_UNITS units) { trace_call("USE_LENGTH_UNITS"); if (active_sink) { - active_sink->use_length_units(units_to_scale(units), event_line()); + active_sink->use_length_units(units_to_scale(units), event_line(), true); } } diff --git a/test-linuxcnc-rs274-native.sh b/test-linuxcnc-rs274-native.sh index e643577..9487e0a 100755 --- a/test-linuxcnc-rs274-native.sh +++ b/test-linuxcnc-rs274-native.sh @@ -1174,6 +1174,10 @@ CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linux # src/emc/rs274ngc/interp_read.cc returns INTERP_ENDFILE at the matching '%', # so later lines are ignored. CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_percent_file_ignores_trailing.ngc >"$output_dir/cnc_sim_linuxcnc_percent_file_ignores_trailing.json" +# Source basis: LinuxCNC unit_tests/interp/test_interp_basics.cc Convert G20 / G21 +# asserts that unit changes rescale current linear axes and work/G92 linear +# offsets while rotary axes remain angular values. +CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_units_current_position.ngc >"$output_dir/cnc_sim_linuxcnc_units_current_position.json" CNC_SIM_RS274_NATIVE_OUTPUT_DIR="$output_dir" python3 - <<'PY' import json import os @@ -1199,6 +1203,27 @@ required_motion = {"set-units", "set-plane", "set-spindle", "rapid", "set-feed", check(OUTPUT_DIR / "cnc_sim_linuxcnc_basic_motion.json", required_motion) check(OUTPUT_DIR / "cnc_sim_linuxcnc_basic_mill.json", required_motion | {"tool-change"}) +units_current_position = load("cnc_sim_linuxcnc_units_current_position.json") +units_rapid = [ + event + for event in units_current_position + if event["type"] == "rapid" +] +if len(units_rapid) != 3: + raise SystemExit(f"unexpected unit-current-position rapid count: {len(units_rapid)}") +if units_rapid[1]["start"] != units_rapid[1]["end"]: + raise SystemExit( + "LinuxCNC G21 current-position rescale was not reflected before the metric no-op rapid: " + f"{units_rapid[1]!r}" + ) +if units_rapid[2]["start"] != units_rapid[2]["end"]: + raise SystemExit( + "LinuxCNC G20 current-position rescale was not reflected before the inch no-op rapid: " + f"{units_rapid[2]!r}" + ) +if (units_rapid[1]["end"]["a"], units_rapid[1]["end"]["b"], units_rapid[1]["end"]["c"]) != (4, 5, 6): + raise SystemExit("LinuxCNC G21 unit change unexpectedly scaled rotary axes") + fractional_linenumbers = load("cnc_sim_linuxcnc_fractional_linenumbers.json") fractional_spindle_states = [ (event["line"], event["spindle"]) @@ -3050,6 +3075,7 @@ echo "dumped $output_dir/cnc_sim_linuxcnc_arc_distance_modes.json" echo "dumped $output_dir/cnc_sim_linuxcnc_arc_center_tolerance_good_imperial.json" echo "dumped $output_dir/cnc_sim_linuxcnc_arc_center_tolerance_tight_metric_default.json" echo "dumped $output_dir/cnc_sim_linuxcnc_arc_center_tolerance_tight_metric_ini.err" +echo "dumped $output_dir/cnc_sim_linuxcnc_units_current_position.json" echo "dumped $output_dir/cnc_sim_linuxcnc_predefined_positions.json" echo "dumped $output_dir/cnc_sim_linuxcnc_machine_coordinates.json" echo "dumped $output_dir/cnc_sim_linuxcnc_cutter_comp.json" diff --git a/test-linuxcnc-source-link.sh b/test-linuxcnc-source-link.sh index e1c5f49..acaba9a 100755 --- a/test-linuxcnc-source-link.sh +++ b/test-linuxcnc-source-link.sh @@ -1858,6 +1858,12 @@ CNC_SIM_RS274_VAR="$var_file" \ CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" \ "$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_percent_file_ignores_trailing.ngc \ >"$output_dir/cnc_sim_linuxcnc_source_percent_file_ignores_trailing.json" +# Source basis: LinuxCNC unit_tests/interp/test_interp_basics.cc Convert G20 / G21 +# asserts that unit changes rescale current linear axes while rotary axes remain +# angular values. +CNC_SIM_RS274_VAR="$var_file" \ + "$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_units_current_position.ngc \ + >"$output_dir/cnc_sim_linuxcnc_source_units_current_position.json" CNC_SIM_RS274_SOURCE_OUTPUT_DIR="$output_dir" python3 - <<'PY' import json @@ -1895,6 +1901,27 @@ required_motion = { check_motion("cnc_sim_linuxcnc_source_basic_motion.json", required_motion) check_motion("cnc_sim_linuxcnc_source_basic_mill.json", required_motion | {"tool-change"}) +units_current_position = load("cnc_sim_linuxcnc_source_units_current_position.json") +units_rapid = [ + event + for event in units_current_position + if event["type"] == "rapid" +] +if len(units_rapid) != 3: + raise SystemExit(f"unexpected source-linked unit-current-position rapid count: {len(units_rapid)}") +if units_rapid[1]["start"] != units_rapid[1]["end"]: + raise SystemExit( + "source-linked LinuxCNC G21 current-position rescale was not reflected before the metric no-op rapid: " + f"{units_rapid[1]!r}" + ) +if units_rapid[2]["start"] != units_rapid[2]["end"]: + raise SystemExit( + "source-linked LinuxCNC G20 current-position rescale was not reflected before the inch no-op rapid: " + f"{units_rapid[2]!r}" + ) +if (units_rapid[1]["end"]["a"], units_rapid[1]["end"]["b"], units_rapid[1]["end"]["c"]) != (4, 5, 6): + raise SystemExit("source-linked LinuxCNC G21 unit change unexpectedly scaled rotary axes") + fractional_linenumbers = load("cnc_sim_linuxcnc_source_fractional_linenumbers.json") fractional_spindle_states = [ (event["line"], event["spindle"]) @@ -4148,3 +4175,4 @@ echo "dumped $output_dir/cnc_sim_linuxcnc_source_fractional_linenumbers.json" echo "dumped $output_dir/cnc_sim_linuxcnc_source_extended_linenumbers.json" echo "dumped $output_dir/cnc_sim_linuxcnc_source_close_and_downcase_words.json" echo "dumped $output_dir/cnc_sim_linuxcnc_source_percent_file_ignores_trailing.json" +echo "dumped $output_dir/cnc_sim_linuxcnc_source_units_current_position.json" diff --git a/tests/gcode/linuxcnc_units_current_position.ngc b/tests/gcode/linuxcnc_units_current_position.ngc new file mode 100644 index 0000000..39690ae --- /dev/null +++ b/tests/gcode/linuxcnc_units_current_position.ngc @@ -0,0 +1,8 @@ +G20 G90 G17 +(Source basis: LinuxCNC unit_tests/interp/test_interp_basics.cc Convert G20 / G21 verifies that current linear axes rescale on unit changes while rotary axes keep angular values.) +G0 X1 Y2 Z3 A4 B5 C6 +G21 +G0 X25.4 Y50.8 Z76.2 A4 B5 C6 +G20 +G0 X1 Y2 Z3 A4 B5 C6 +M30