按源同步单位切换当前位置

结论:依据 LinuxCNC interp_convert.cc convert_length_units 与 unit_tests/interp/test_interp_basics.cc,G20/G21 切换时事件桥同步重标定当前线性坐标,native/source-link 覆盖通过。
This commit is contained in:
cnc
2026-06-06 08:15:59 +08:00
parent 10bf0a5897
commit ccd51ff373
6 changed files with 99 additions and 1 deletions

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -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"

View File

@@ -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"

View File

@@ -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