Skip to content

Commit 1243bd4

Browse files
committed
interp: G92, G10 L20, G43 and M6 wait for the G49 that cancels G43.4
Under the kinematics G43.4 or G43.5 switches to, the current point is the tool tip, with the tool length along the tilted tool. G92 made that point the coordinates given and kept the offset after the G49, where the same numbers name another point: the spindle nose, or wherever the tilt put the length. G10 L20 did the same into a coordinate system. M6 changed the tool under the tip the program follows, so the point moved with the new length. A plain G43 changed the length and ended G43.4's hold on the kinematics, so G92 then passed with the machine still tilted on them and G49 no longer switched back. All of them ran without a word. Fanuc refuses G92 and G43 in tool centre point control (PS5421, not in its list of G codes allowed under G43.4/G43.5), Siemens refuses PRESETON on axes under a transformation (17600), and Heidenhain resets M128/TCPM before a TOOL CALL. G92, G92.1, G92.2, G92.3, G10 L20 and M6 are now refused while the switch G43.4 or G43.5 made is in effect, with a message to cancel it with G49 first; G43 is refused with a message to change the length with G43.4 H (G43.5 H under G43.5). G43.1 and G43.2 change the values of the offset in effect, the only way to give an offset across the tool, and keep the switch. G10 L2, G52 and G54 to G59.3 stay: they read no position, and Siemens and Heidenhain allow their frames and datum shifts under TCP (Fanuc refuses G52 and G54 to G59 too, tied to its own TCP coordinate handling). The rule follows the switch G43.4 made, not the kinematics type: once G12.1 or G13.1 has selected a kinematics the program has taken it over, and a hexapod or robot running G43 on its primary type keeps its codes; on a machine without switchable kinematics G43.4 is a plain G43 and nothing changes. Under a tilted work plane G92 and G10 were already refused and G52 shifts the plane. convert_g92_is_applied's result was stored and never checked, so every refusal of G92.1, G92.2 and G92.3 was dropped and the code did nothing without saying so: under cutter radius compensation and under a tilted work plane as well as here. It is checked now. tests/kins-switch: under G43.4, G92 X1, G92.1, G92.2, G92.3, T1 M6, G43 H1 and G10 L20 are each refused with the message; G43.4 H1, G10 L2, G52 and G55 pass, and after G43.1 or G43.2 G92 is still refused; under G43.5 G92, M6 and G43 are refused; after G49, and under G43 on a type G12.1 selected, G92, G92.1, M6 and G10 L20 pass. Each refusal aborts and the test's abort routine selects G13.1, so G43.4 is programmed again before each one. Without the change 12 checks fail; 12 of 12 runs pass and 12 of 12 fail as expected without it, at 6 copies in parallel with 4 busy loops, and 3 of 3 pass and fail likewise with 3 copies and a busy loop all on one CPU.
1 parent cf83539 commit 1243bd4

5 files changed

Lines changed: 171 additions & 23 deletions

File tree

‎docs/src/gcode/g-code.adoc‎

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -941,6 +941,8 @@ It is an error if:
941941

942942
* The P number does not evaluate to an integer in the range 0 to 9.
943943
* An axis is programmed that is not defined in the configuration.
944+
* '<<gcode:g43.4,G43.4>>' or 'G43.5' is in effect; cancel it with 'G49'
945+
first.
944946

945947
[[gcode:g12.1-g13.1]]
946948
== G12.1, G13.1 Select Kinematics(((G12.1, G13.1 Select Kinematics)))
@@ -1862,8 +1864,7 @@ compensation in the module's working kinematics. The switch happens
18621864
first and the offset applies after it, as if the two had been written
18631865
on consecutive lines. 'G49' is the matching cancel: it clears the
18641866
offset and switches back to the machine frame kinematics, what 'G13.1'
1865-
selects, as long as the offset in effect is still 'G43.4''s and no 'G12.1'
1866-
or 'G13.1' has selected a kinematics since.
1867+
selects, as long as no 'G12.1' or 'G13.1' has selected a kinematics since.
18671868

18681869
The H word, the offset itself and the parameters it lands in are
18691870
'G43''s. Which kinematics is the working one is declared by the module
@@ -1892,6 +1893,19 @@ frame sets `MACHINE_MOVES_IN_MACHINE_FRAME` in the `[RS274NGC]` section of the
18921893
INI file, as the five axis sims shipped with LinuxCNC do; see
18931894
<<gcode:g53,G53>>.
18941895

1896+
While the switch 'G43.4' made is in effect, '<<gcode:g92,G92>>', 'G92.1',
1897+
'G92.2', 'G92.3', '<<gcode:g10-l20,G10 L20>>' and '<<mcode:m6,M6>>' are
1898+
refused until 'G49' cancels it. The current point is then the tool tip,
1899+
with the tool length along the tilted tool: offsets a 'G92' or 'G10 L20'
1900+
takes from it stay after 'G49', where the same numbers name another point,
1901+
and a tool change moves the point with the tool length. A new tool length
1902+
from the tool table is 'G43.4 H-': a plain 'G43' is refused, since it would
1903+
end the switch with the machine left on the working kinematics, while
1904+
'G43.1' and 'G43.2' change the values of the offset in effect and keep the
1905+
switch. Once
1906+
'G12.1' or 'G13.1' has selected a kinematics, and on a machine without
1907+
switchable kinematics, these codes work as usual.
1908+
18951909
It is an error if:
18961910

18971911
* the kinematics module is switchable but declares no primary
@@ -3705,7 +3719,11 @@ on the action of `G92`.
37053719
If this is the case, the offset is replaced with a new
37063720
offset that makes the current point become the specified value.
37073721

3708-
It is an error if all axis words are omitted.
3722+
It is an error if:
3723+
3724+
* all axis words are omitted, or
3725+
* '<<gcode:g43.4,G43.4>>' or 'G43.5' is in effect; cancel it with 'G49'
3726+
first.
37093727

37103728
LinuxCNC stores the G92 offsets and reuses them on the next run of a
37113729
program. To prevent this, one can program a `G92.1` (to erase them), or
@@ -3725,6 +3743,8 @@ See the <<sec:overview-parameters,Parameters>> section for more information.
37253743
* 'G92.1' - turn off G92 offsets and reset <<sub:numbered-parameters,parameters>> 5211 - 5219 to zero.
37263744
* 'G92.2' - turn off G92 offsets but keep <<sub:numbered-parameters,parameters>> 5211 - 5219 available.
37273745

3746+
Like 'G92', both are an error while '<<gcode:g43.4,G43.4>>' or 'G43.5' is in effect.
3747+
37283748
[NOTE]
37293749
G92.1 only clears G92 offsets, to change G53-G59.3 coordinate system offsets in G-code use either <<gcode:g10-l2,G10 L2>> or <<gcode:g10-l20,G10 L20>>.
37303750

@@ -3741,6 +3761,8 @@ The parameter values will be saved when the first program exits and restored whe
37413761
Use `G92.3` near the beginning of the second program.
37423762
That will restore the offsets saved in the first program.
37433763

3764+
Like 'G92', 'G92.3' is an error while '<<gcode:g43.4,G43.4>>' or 'G43.5' is in effect.
3765+
37443766
[[gcode:g93-g94-g95]]
37453767
== G93, G94, G95 Feed Rate Mode(((G93, G94, G95 Feed Rate Mode)))
37463768

‎docs/src/gcode/m-code.adoc‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,12 @@ the carousel (not its index).
190190
The tool length offset is not changed by 'M6', use '<<gcode:g43,G43>>' after the
191191
'M6' to change the tool length offset.
192192

193+
'M6' is an error while '<<gcode:g43.4,G43.4>>' or 'G43.5' is in effect: the
194+
point the program follows is the tool tip, which the new tool length would
195+
move. Cancel it with 'G49' on a line before the 'M6' (on the same line the
196+
tool change runs first, see <<gcode:order-of-execution,Order of Execution>>),
197+
change the tool, then program 'G43.4' again.
198+
193199
The tool change may include axis motion.
194200
It is OK (but not useful) to program a change to the tool already in the spindle.
195201
It is OK if there is no tool in the selected slot;

‎src/emc/rs274ngc/interp_convert.cc‎

Lines changed: 50 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1572,6 +1572,36 @@ int Interp::convert_arc_comp2(int move, //!< either G_2 (cw arc) or G_3 (ccw ar
15721572

15731573
/****************************************************************************/
15741574

1575+
// the kinematics module declares what each type is (KINSTYPE_* flags);
1576+
// where the flags say nothing at all there is no kinematics attached
1577+
// (sai, a preview with no machine to ask) and the codes fall back to
1578+
// type 0, as before
1579+
static int kins_type_info_available()
1580+
{
1581+
int k;
1582+
1583+
for (k = 0; k < SWITCHKINS_MAX_TYPES; k++) {
1584+
if (GET_EXTERNAL_KINS_TYPE_FLAGS(k) >= 0) return 1;
1585+
}
1586+
return 0;
1587+
}
1588+
1589+
// G43.4 or G43.5 has put the machine on its working kinematics with the
1590+
// tool length along the tool: the current point is the tool tip, which a
1591+
// G92 would bake into offsets that outlive the G49, and a tool change
1592+
// would move it. Without switchable kinematics G43.4 is a plain G43.
1593+
static bool tcp_armed(setup_pointer settings)
1594+
{
1595+
return settings->kins_by_g43_4 && kins_type_info_available();
1596+
}
1597+
1598+
static const char *tcp_code(setup_pointer settings)
1599+
{
1600+
return settings->tool_vector ? "G43.5" : "G43.4";
1601+
}
1602+
1603+
/****************************************************************************/
1604+
15751605
/*! convert_axis_offsets
15761606
15771607
Returned Value: int
@@ -1647,6 +1677,10 @@ int Interp::convert_axis_offsets(int g_code, //!< g_code being executed (mus
16471677
_("Cannot change G92 offsets while a tilted work plane (G68.2) is active"));
16481678
return work_plane_local(block, settings);
16491679
}
1680+
// G52 shifts the program's coordinates and reads no position
1681+
CHKS((g_code != G_52 && tcp_armed(settings)),
1682+
_("Cannot change G92 offsets while %s is active, cancel it with G49 first"),
1683+
tcp_code(settings));
16501684
CHKS((block->a_flag && settings->axis_wrapped[AXIS_A] &&
16511685
(block->a_number <= -360.0 || block->a_number >= 360.0)),
16521686
(_("Invalid absolute position %5.2f for wrapped rotary axis %c")),
@@ -3050,6 +3084,7 @@ int Interp::convert_g(block_pointer block, //!< pointer to a block of RS27
30503084
}
30513085
if ((block->g_modes[GM_G92_IS_APPLIED] != -1) && ONCE(STEP_G92_IS_APPLIED)) {
30523086
status = convert_g92_is_applied(block->g_modes[GM_G92_IS_APPLIED], block, settings);
3087+
CHP(status);
30533088
}
30543089
if ((block->motion_to_be != -1) && ONCE(STEP_MOTION)){
30553090
status = convert_motion(block->motion_to_be, block, settings);
@@ -4181,6 +4216,9 @@ int Interp::convert_m(block_pointer block, //!< pointer to a block of RS27
41814216

41824217
switch (block->m_modes[6]) {
41834218
case 6:
4219+
CHKS(tcp_armed(settings),
4220+
_("Cannot change tools while %s is active, cancel it with G49 first"),
4221+
tcp_code(settings));
41844222
if (is_user_defined_m_code(block, settings, 6) && remapped_in_block) {
41854223
return convert_remapped_code(block,settings,
41864224
STEP_M_6,
@@ -5027,6 +5065,10 @@ int Interp::convert_setup(block_pointer block, //!< pointer to a block of RS27
50275065

50285066
CHKS((settings->g68_active),
50295067
_("Cannot use G10 L%d while a tilted work plane (G68.2) is active"), block->l_number);
5068+
// L20 reads the current point, the tool tip under G43.4, like G92
5069+
CHKS((block->l_number == 20 && tcp_armed(settings)),
5070+
_("Cannot use G10 L20 while %s is active, cancel it with G49 first"),
5071+
tcp_code(settings));
50305072
double *parameters;
50315073
int p_int;
50325074

@@ -6660,20 +6702,6 @@ int Interp::convert_tool_change(setup_pointer settings) //!< pointer to machine
66606702

66616703
/****************************************************************************/
66626704

6663-
// the kinematics module declares what each type is (KINSTYPE_* flags);
6664-
// where the flags say nothing at all there is no kinematics attached
6665-
// (sai, a preview with no machine to ask) and the codes fall back to
6666-
// type 0, as before
6667-
static int kins_type_info_available()
6668-
{
6669-
int k;
6670-
6671-
for (k = 0; k < SWITCHKINS_MAX_TYPES; k++) {
6672-
if (GET_EXTERNAL_KINS_TYPE_FLAGS(k) >= 0) return 1;
6673-
}
6674-
return 0;
6675-
}
6676-
66776705
// the lowest type carrying a KINSTYPE_ flag, or -1 when the module declares none;
66786706
// -1 for a type is "no information", and it matches every flag, so it must
66796707
// be excluded before the bit test
@@ -6742,6 +6770,11 @@ int Interp::convert_tool_length_offset(int g_code, //!< g_code being execu
67426770

67436771
CHKS((settings->cutter_comp_side != CUTTER_COMP::OFF),
67446772
(_("Cannot change tool offset with cutter radius compensation on")));
6773+
// under G43.4 a new length from the table is G43.4 H-: a plain G43
6774+
// would end G43.4's hold on the kinematics with the machine left on them
6775+
CHKS((g_code == G_43 && tcp_armed(settings)),
6776+
_("Cannot use G43 while %s is active, change the tool length with %s H-"),
6777+
tcp_code(settings), tcp_code(settings));
67456778
if (g_code == G_43_4 || g_code == G_43_5) {
67466779
int primary = flagged_kins_type(KINSTYPE_PRIMARY);
67476780
int now = GET_EXTERNAL_KINS_TYPE_FLAGS(settings->kins_type);
@@ -6767,8 +6800,9 @@ int Interp::convert_tool_length_offset(int g_code, //!< g_code being execu
67676800
CHP(snap_after_switch(settings, standing, have_standing));
67686801
}
67696802
settings->kins_by_g43_4 = true;
6770-
} else if (g_code != G_49) {
6771-
// the offset in effect is no longer G43.4's, so G49 has no switch to undo
6803+
} else if (g_code == G_43) {
6804+
// the offset in effect is no longer G43.4's, so G49 has no switch to
6805+
// undo; G43.1 and G43.2 change the values of the offset in effect
67726806
settings->kins_by_g43_4 = false;
67736807
}
67746808
settings->tool_vector = (g_code == G_43_5);

‎tests/kins-switch/README‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,8 @@ agreeing on where the point went, that under G43.5 a tool vector I J K
1414
lands on the joints and the point the rotary words reach, is not
1515
incremental, keeps the free joint on the pole and is refused with a
1616
rotary word, as a zero vector, on the identity kinematics and outside
17-
G43.5, and that G13.1 in an ON_ABORT_COMMAND routine does not swallow
18-
the rest of the routine.
17+
G43.5, that G92, G92.1, G92.2, G92.3, M6, plain G43 and G10 L20 are
18+
refused while G43.4 or G43.5 is in effect and work again after G49 or on
19+
a type G12.1 selected, while G43.4 H, G43.1, G43.2, G10 L2, G52 and G55
20+
pass under it and G43.1 and G43.2 keep it in effect, and that G13.1 in an ON_ABORT_COMMAND
21+
routine does not swallow the rest of the routine.

‎tests/kins-switch/test-ui.py‎

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -273,12 +273,23 @@ def tool_length_check(what, before_joints, before_pose, after_joints, after_pose
273273
# (-sin B cos C, -sin B sin C, cos B), so the vector for the tilted pose
274274
# above has to land on the joints and the point the rotary words reach.
275275

276+
def said_error(timeout=5):
277+
# the error can reach the channel after the command reports done
278+
deadline = time.time() + timeout
279+
while time.time() < deadline:
280+
m = e.poll()
281+
if m and m[0] in (linuxcnc.NML_ERROR, linuxcnc.OPERATOR_ERROR):
282+
return m
283+
if not m:
284+
time.sleep(0.01)
285+
return None
286+
276287
def refused(cmd, needle):
277288
drain()
278289
c.mdi(cmd)
279290
c.wait_complete(30)
280-
m = e.poll()
281-
if not m or m[0] not in (linuxcnc.NML_ERROR, linuxcnc.OPERATOR_ERROR):
291+
m = said_error()
292+
if not m:
282293
error("%s was accepted" % cmd)
283294
elif needle not in m[1]:
284295
error("%s said %r, nothing about %r" % (cmd, m[1].strip(), needle))
@@ -412,6 +423,78 @@ def param(name):
412423
print("refused as expected: %s" % m[1].strip())
413424
drain()
414425

426+
# ---- G92, M6, G43 and G10 L20 while G43.4 or G43.5 is on ------------------
427+
#
428+
# Under TCP the current point is the tool tip with the length along the
429+
# tilted tool: a G92 or G10 L20 would bake it into offsets that outlive the
430+
# G49, and a tool change would move it, so they wait for the G49. A new
431+
# length from the table is G43.4 H, a plain G43 would end G43.4's hold on
432+
# the kinematics. G10 L2, G52 and G54 to G59 read no position, so they stay.
433+
# The same tool length on a type the program selected itself is its own
434+
# business.
435+
436+
def accepted(cmd):
437+
drain()
438+
mdi(cmd)
439+
said = [m for m in drain() if m[0] in (linuxcnc.NML_ERROR, linuxcnc.OPERATOR_ERROR)]
440+
if said:
441+
error("%s was refused: %s" % (cmd, said[0][1].strip()))
442+
443+
def refused_under(tcp, cmd, needle):
444+
# the refusal aborts, and this test's abort routine selects G13.1
445+
mdi(tcp + " H1")
446+
refused(cmd, needle)
447+
448+
errors_before = errors
449+
mdi("G13.1")
450+
mdi("G0 X0 Y0 Z0 B-20 C30 W0")
451+
for cmd in ("G92 X1", "G92.1", "G92.2", "G92.3"):
452+
refused_under("G43.4", cmd, "while G43.4 is active, cancel it with G49 first")
453+
refused_under("G43.4", "T1 M6", "Cannot change tools while G43.4")
454+
refused_under("G43.4", "G43 H1", "change the tool length with G43.4 H-")
455+
refused_under("G43.4", "G10 L20 P2 X1", "Cannot use G10 L20 while G43.4 is active")
456+
mdi("G43.4 H1")
457+
accepted("G43.4 H1")
458+
# G43.1 and G43.2 change the values of the offset in effect: G43.4 still
459+
# holds the kinematics, and G92 still waits for the G49
460+
accepted("G43.1 Z1")
461+
refused("G92 X1", "while G43.4 is active")
462+
mdi("G43.4 H1")
463+
accepted("G43.2 H1")
464+
refused("G92 X1", "while G43.4 is active")
465+
mdi("G43.4 H1")
466+
accepted("G10 L2 P2 X1")
467+
accepted("G10 L2 P2 X0")
468+
accepted("G52 X1")
469+
accepted("G52 X0")
470+
accepted("G55")
471+
s.poll()
472+
if s.g5x_index != 2:
473+
error("G55 under G43.4 left G%d" % (53 + s.g5x_index))
474+
accepted("G54")
475+
refused_under("G43.5", "G92 X1", "while G43.5 is active")
476+
refused_under("G43.5", "T1 M6", "while G43.5 is active")
477+
refused_under("G43.5", "G43 H1", "change the tool length with G43.5 H-")
478+
mdi("G43.5 H1")
479+
mdi("G49")
480+
if kins_type() != 1:
481+
error("G49 left kinematics %d, not the identity" % kins_type())
482+
accepted("G92 X1")
483+
accepted("G92.1")
484+
accepted("T1 M6")
485+
accepted("G10 L20 P2 X1")
486+
accepted("G10 L2 P2 X0")
487+
mdi("G12.1 P0")
488+
mdi("G43 H1")
489+
accepted("G92 X1")
490+
accepted("G92.1")
491+
accepted("T1 M6")
492+
mdi("G49")
493+
mdi("G13.1")
494+
mdi("G0 X0 Y0 Z0 B0 C0 W0")
495+
if errors == errors_before:
496+
print("G43.4 and G43.5 hold G92, M6, G43 and G10 L20 back; G43.4 H, G43.1, G43.2, G10 L2, G52 and G54 to G59 pass")
497+
415498
# ---- G13.1 in an abort routine does not swallow the rest of it -----------
416499
#
417500
# The routine ends with G54, so leave the machine in G55 and see which one

0 commit comments

Comments
 (0)