Skip to content

Commit 7380a1e

Browse files
committed
docs, tests: document and cover G28.2
Docs: new "G28.2 Home from G-code" section in g-code.adoc (syntax, the mandatory P word and why there is no bare form, the HOME_SEQUENCE requirement for P-1, the negative/positive shared-sequence Pn cases, the mode-dip and position-resync behaviour, error conditions); G28.2 added to the modal-group-0 lists in overview.adoc, remap.adoc, gcode.html.in, hal_glib.py and mdi_text.py, with the qtvcp MDI help carrying the same P-word rules. Tests (tests/interp/g28.2/): joint-pword and invalid-pword drive rs274 / task directly; the rest run a sim under milltask - - sequencing: the FREE-mode dip is invisible at the task level; an invalid Pn does not wedge task.mode; - immediate-mode-guard: an immediate home from teleop is still refused; - home-all-sequence: G28.2 P-1 as a first-home on a HOME_SEQUENCE config, and a bare G28.2 refused without homing anything; - invalid-pword: the rest of the P word's surface - an unconfigured joint number, P-2, another negative and a fraction are all refused up front, name P-1 as the way to home everything, and leave the homed state and trajectory mode alone; - flush-order: a move before G28.2 runs before the home; - position-model: a G91 move (rotary C and linear X) after G28.2 Pn is computed from the homed position, not the stale one - fails without the resync (lands at stale+increment).
1 parent f1574fc commit 7380a1e

42 files changed

Lines changed: 1691 additions & 3 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/src/gcode.html.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ tr.head td, tr.head th { background: black; color: white; }
165165
<tr><td><a href="gcode/g-code.html#gcode:g10-l2">G10 L2</a></td><td>P R</td><td>Set Coordinate System</td></tr>
166166
<tr><td><a href="gcode/g-code.html#gcode:g10-l20">G10 L20</a></td><td>P</td><td>Set Coordinate System</td></tr>
167167
<tr><td><a href="gcode/g-code.html#gcode:g28-g28.1">G28, G28.1</a></td><td/><td>Go/Set Predefined Position</td></tr>
168+
<tr><td><a href="gcode/g-code.html#gcode:g28.2">G28.2</a></td><td>P</td><td>Home from G-code</td></tr>
168169
<tr><td><a href="gcode/g-code.html#gcode:g30-g30.1">G30, G30.1</a></td><td/><td>Go/Set Predefined Position</td></tr>
169170
<tr><td><a href="gcode/g-code.html#gcode:g53">G53</a></td><td/><td>Move in Machine Coordinates</td></tr>
170171
<tr><td><a href="gcode/g-code.html#gcode:g92">G52, G92</a></td><td/><td>Coordinate System Offset</td></tr>

docs/src/gcode/g-code.adoc

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ as the 'L number', and so on for any other letter.
7373
|<<gcode:g17-g19.1,G17 - G19.1>> |Plane Select
7474
|<<gcode:g20-g21,G20 G21>> |Set Units of Measure
7575
|<<gcode:g28-g28.1,G28 - G28.1>> |Go to Predefined Position
76+
|<<gcode:g28.2,G28.2>> |Home from G-code
7677
|<<gcode:g30-g30.1,G30 - G30.1>> |Go to Predefined Position
7778
|<<gcode:g33,G33>> |Spindle Synchronized Motion
7879
|<<gcode:g33.1,G33.1>> |Rigid Tapping
@@ -997,6 +998,81 @@ It is an error if :
997998

998999
* Cutter Compensation is turned on
9991000

1001+
[[gcode:g28.2]]
1002+
== G28.2 Home from G-code(((G28.2 Home from G-code)))
1003+
1004+
This non-modal code lets a program or MDI line reference the machine
1005+
instead of requiring the operator to use the GUI's *Home All* button. It
1006+
follows the same modal-group-0 pattern as `G28.1`/`G30.1`, takes no axis
1007+
words, and *requires* a `P` word saying what to home.
1008+
1009+
* 'G28.2 P-1' - runs the homing cycle on every joint, in `HOME_SEQUENCE`
1010+
order (the same operation as the GUI *Home All*). This form requires the
1011+
config to set `[JOINT_n]HOME_SEQUENCE`; exactly as with *Home All*, a
1012+
config with no `HOME_SEQUENCE` cannot home all joints at once and the
1013+
command fails, leaving the machine in joint mode.
1014+
* 'G28.2 Pn' - runs the homing cycle on joint 'n' only, where 'n' is the
1015+
0-based joint number matching its `[JOINT_n]` INI section (the same
1016+
numbering used by `HOME_SEQUENCE` and by joint jogging). Other joints are
1017+
left as they are, and `HOME_SEQUENCE` is not required for the `Pn` form.
1018+
How many joints actually home depends on the `HOME_SEQUENCE` of joint 'n':
1019+
+
1020+
--
1021+
** a *negative* (synchronized) sequence homes the whole synchronized group -
1022+
`Pn` on either joint of a gantry pair homes both;
1023+
** a *positive* sequence shared with other joints homes only joint 'n' -
1024+
use `G28.2 P-1` to home the shared group together;
1025+
** no sequence, or a sequence not shared with any other joint, homes just
1026+
joint 'n'.
1027+
--
1028+
1029+
[WARNING]
1030+
There is no bare `G28.2`. Homing drives joints onto their switches at
1031+
homing speed, ignoring soft limits, from wherever the machine happens to
1032+
be, so homing the whole machine has to be asked for explicitly with `P-1`
1033+
rather than being what a truncated or mistyped line does. A `G28.2` with no
1034+
`P` word is an error and stops the program.
1035+
1036+
.G28.2 Example Lines
1037+
[source,ngc]
1038+
----
1039+
G28.2 P-1 (home all joints, in HOME_SEQUENCE order)
1040+
G28.2 P1 (home joint 1 only)
1041+
----
1042+
1043+
A queued `G28.2` dips motion into free mode for the duration of the homing
1044+
cycle and restores whatever mode (manual/MDI/auto) was active once it
1045+
finishes, so the mode dip is invisible at the task level. Motion still
1046+
enforces its own safety: the home is honored only when the machine is idle
1047+
(in position with no queued motion) or in joint mode, and a home is refused
1048+
mid-motion. Homing inhibits and per-joint limit handling are unchanged.
1049+
1050+
[NOTE]
1051+
When the homing cycle finishes, the interpreter resyncs its model of the
1052+
current position from the machine (the same way it does after probing or a
1053+
tool change), so a following move made in incremental distance mode
1054+
(`G91`), or an arc whose center is given with `I`/`J`/`K`, is computed from
1055+
where the machine actually is after homing. `G28.2` is a queue point: read
1056+
ahead stops at it and resumes once the cycle has run. `G5x`/`G92` offsets
1057+
that were active before the `G28.2` are still applied afterward and now
1058+
refer to the newly established machine zero; clear or re-establish them if
1059+
that is not what you want.
1060+
1061+
[NOTE]
1062+
There is no G-code unhome. Clearing a joint's reference is done from the
1063+
GUI, halui or linuxcncrsh.
1064+
1065+
[NOTE]
1066+
`G28.2` is a LinuxCNC extension; there is no standard Fanuc equivalent.
1067+
1068+
It is an error if:
1069+
1070+
* Cutter radius compensation is active (`G41`, `G41.1`, `G42` or `G42.1`).
1071+
* An axis word is present ('G28.2' takes no axis words).
1072+
* The 'P' word is missing.
1073+
* The 'P' word is not a whole number, or is negative other than `P-1`.
1074+
* The 'P' word names a joint number the machine does not have.
1075+
10001076
[[gcode:g30-g30.1]]
10011077
== G30, G30.1 Go/Set Predefined Position(((G30 Go/Set Predefined Position)))
10021078

docs/src/gcode/overview.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -960,7 +960,7 @@ The modal groups are shown in the following Table.
960960
[width="80%",cols="4,6",options="header"]
961961
|===
962962
|Modal Group Meaning | Member Words
963-
|Non-modal codes (Group 0) | G4, G10 G28, G30, G52, G53, G92, G92.1, G92.2, G92.3,
963+
|Non-modal codes (Group 0) | G4, G10 G28, G28.2, G30, G52, G53, G92, G92.1, G92.2, G92.3,
964964
|Motion (Group 1) | G0, G1, G2, G3, G33, G38.n, G73, G76, G80, G81
965965
G82, G83, G84, G85, G86, G87, G88, G89
966966
|Plane selection (Group 2) | G17, G18, G19, G17.1, G18.1, G19.1

docs/src/remap/remap.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1851,7 +1851,7 @@ All the listed G-codes are already defined in the current implementation of Linu
18511851
|25 | | | | | | | | | |
18521852
|26 | | | | | | | | | |
18531853
|27 | | | | | | | | | |
1854-
|28 |G28 |G28.1 | | | | | | | |
1854+
|28 |G28 |G28.1 |G28.2 | | | | | | |
18551855
|29 | | | | | | | | | |
18561856
|===
18571857

lib/python/common/hal_glib.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ class _GStat(GObject.GObject):
287287
STATE_ON = linuxcnc.STATE_ON
288288
STATE_OFF = linuxcnc.STATE_OFF
289289

290-
group0 = ('G4', 'G10','G28', 'G30', 'G52', 'G53', 'G92', 'G92.1', 'G92.2', 'G92.3')
290+
group0 = ('G4', 'G10','G28', 'G28.2', 'G30', 'G52', 'G53', 'G92', 'G92.1', 'G92.2', 'G92.3')
291291
group1 = ('G0', 'G1', 'G2', 'G3', 'G33', 'G38.n', 'G73', 'G76', 'G80', 'G81',\
292292
'G82', 'G83', 'G84', 'G85', 'G86', 'G87', 'G88', 'G89')
293293
group2 = ('G17', 'G18', 'G19', 'G17.1', 'G18.1', 'G19.1')

lib/python/qtvcp/lib/mdi_text.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ def gcode_titles():
2727
'G21': 'Set Units to Millimeters',
2828
'G28': 'Go to Predefined Position',
2929
'G28.1': 'Set Predefined Position',
30+
'G28.2': 'Home from G-code',
3031
'G30': 'Go to Predefined Position',
3132
'G30.1': 'Set Predefined Position',
3233
'G33': 'Spindle Synchronized Motion',
@@ -209,6 +210,7 @@ def gcode_descriptions(gcode):
209210
'G21': G21,
210211
'G28': G28,
211212
'G28.1': G28_1,
213+
'G28.2': G28_2,
212214
'G30': G30,
213215
'G30.1': G30_1,
214216
'G33': G33,
@@ -467,6 +469,29 @@ def gcode_descriptions(gcode):
467469
G28.1 - stores the current absolute position into
468470
parameters 5161-5166.
469471
"""
472+
473+
G28_2 = """G28.2 Home from G-code
474+
Runs the homing cycle, the same operation as the GUI
475+
Home All button, so a program or MDI line can
476+
reference the machine. Takes no axis words, and
477+
requires a P word saying what to home.
478+
479+
G28.2 P-1 - homes all joints, in HOME_SEQUENCE order
480+
(the config must set HOME_SEQUENCE).
481+
482+
G28.2 Pn - homes joint n only, where n is the
483+
0-based joint number matching its [JOINT_n] INI
484+
section. On a synchronized (negative HOME_SEQUENCE)
485+
joint pair, Pn on either joint homes both.
486+
487+
There is no bare G28.2: homing the whole machine has
488+
to be asked for with P-1.
489+
490+
It is an error if cutter compensation is on, if the P
491+
word is missing or is not -1 or a whole joint number,
492+
or if Pn names a joint the machine does not have.
493+
"""
494+
470495
G30 = """G30 Go to Predefined Position
471496
G30 uses the values stored in parameters 5181-5189
472497
as the X Y Z A B C U V W final point to move to.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/sh
2+
exit 0 # test failure is indicated by test.sh exit value

tests/interp/g28.2/flush-order/sim.tbl

Whitespace-only changes.
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
#!/usr/bin/env python3
2+
3+
"""
4+
Regression test for the flush_segments() ordering fix in HOME_CYCLE()/
5+
HOME_CYCLE()/HOME_CYCLE_JOINT()
6+
(emccanon.cc).
7+
8+
STRAIGHT_FEED/STRAIGHT_TRAVERSE buffer points into chained_points for
9+
arc-blend lookahead and only reach interp_list on a flush (see
10+
see_segment()/flush_segments()). Without an explicit flush_segments() call
11+
at the start of the home canon functions, a queued move immediately
12+
before a G28.2 could silently get reordered to run *after* the home
13+
instead of before it.
14+
15+
test.ngc queues "G1 X2" (a multi-cycle move, slow enough to poll mid-flight)
16+
immediately followed by "G28.2 P0". This script polls position and homed
17+
state throughout the run and asserts joint 0 never reports homed=1 before
18+
its position has actually reached the X2 target -- if the move were
19+
silently deferred to after the home (the bug), homed would flip true while
20+
position was still near its starting point.
21+
"""
22+
23+
import linuxcnc
24+
import hal
25+
26+
import sys
27+
import time
28+
29+
h = hal.component("python-ui")
30+
h.ready()
31+
32+
c = linuxcnc.command()
33+
s = linuxcnc.stat()
34+
35+
36+
def poll():
37+
s.poll()
38+
39+
40+
def fail(msg):
41+
print("FAIL: " + msg)
42+
sys.exit(1)
43+
44+
45+
c.state(linuxcnc.STATE_ESTOP_RESET)
46+
c.state(linuxcnc.STATE_ON)
47+
c.mode(linuxcnc.MODE_AUTO)
48+
time.sleep(0.2)
49+
50+
c.program_open("test.ngc")
51+
time.sleep(0.2)
52+
c.auto(linuxcnc.AUTO_RUN, 0)
53+
54+
saw_position_near_target = False
55+
homed_while_short_of_target = None
56+
t0 = time.time()
57+
while time.time() - t0 < 10.0:
58+
poll()
59+
if s.position[0] > 1.9:
60+
saw_position_near_target = True
61+
if s.homed[0] and not saw_position_near_target:
62+
homed_while_short_of_target = s.position[0]
63+
break
64+
if s.exec_state == linuxcnc.EXEC_DONE and s.interp_state == linuxcnc.INTERP_IDLE:
65+
break
66+
time.sleep(0.001)
67+
68+
if homed_while_short_of_target is not None:
69+
fail("joint 0 reported homed while X was still at {} (target 2.0) -- "
70+
"the queued move was reordered to run after G28.2 P0".format(homed_while_short_of_target))
71+
72+
if not saw_position_near_target:
73+
fail("X never reached its target -- move did not run at all")
74+
75+
t1 = time.time()
76+
while time.time() - t1 < 5.0:
77+
poll()
78+
if s.exec_state == linuxcnc.EXEC_DONE and s.interp_state == linuxcnc.INTERP_IDLE:
79+
break
80+
time.sleep(0.01)
81+
82+
if not s.homed[0]:
83+
fail("joint 0 never ended up homed")
84+
85+
print("PASS: the queued move completed before G28.2 P0 homed the joint")
86+
print("done! it all worked")
87+
sys.exit(0)
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
[EMC]
2+
DEBUG = 0
3+
VERSION = 1.1
4+
5+
[DISPLAY]
6+
DISPLAY = ./test-ui.py
7+
8+
[TASK]
9+
TASK = milltask
10+
CYCLE_TIME = 0.001
11+
12+
[RS274NGC]
13+
PARAMETER_FILE = sim.var
14+
15+
[EMCMOT]
16+
EMCMOT = motmod
17+
COMM_TIMEOUT = 4.0
18+
BASE_PERIOD = 0
19+
SERVO_PERIOD = 1000000
20+
21+
[HAL]
22+
HALUI = halui
23+
HALFILE = LIB:core_sim.hal
24+
25+
[TRAJ]
26+
NO_FORCE_HOMING = 1
27+
AXES = 3
28+
COORDINATES = X Y Z
29+
HOME = 0 0 0
30+
LINEAR_UNITS = inch
31+
ANGULAR_UNITS = degree
32+
DEFAULT_LINEAR_VELOCITY = 1.2
33+
MAX_LINEAR_VELOCITY = 4
34+
35+
[KINS]
36+
JOINTS = 3
37+
KINEMATICS = trivkins
38+
39+
[AXIS_X]
40+
MAX_VELOCITY = 4
41+
MAX_ACCELERATION = 1000.0
42+
MIN_LIMIT = -40.0
43+
MAX_LIMIT = 40.0
44+
45+
[AXIS_Y]
46+
MAX_VELOCITY = 4
47+
MAX_ACCELERATION = 1000.0
48+
MIN_LIMIT = -40.0
49+
MAX_LIMIT = 40.0
50+
51+
[AXIS_Z]
52+
MAX_VELOCITY = 4
53+
MAX_ACCELERATION = 1000.0
54+
MIN_LIMIT = -4.0
55+
MAX_LIMIT = 4.0
56+
57+
[JOINT_0]
58+
TYPE = LINEAR
59+
HOME = 0.000
60+
MAX_VELOCITY = 4
61+
MAX_ACCELERATION = 1000.0
62+
BACKLASH = 0.000
63+
INPUT_SCALE = 4000
64+
OUTPUT_SCALE = 1.000
65+
MIN_LIMIT = -40.0
66+
MAX_LIMIT = 40.0
67+
FERROR = 0.050
68+
MIN_FERROR = 0.010
69+
70+
[JOINT_1]
71+
TYPE = LINEAR
72+
HOME = 0.000
73+
MAX_VELOCITY = 4
74+
MAX_ACCELERATION = 1000.0
75+
BACKLASH = 0.000
76+
INPUT_SCALE = 4000
77+
OUTPUT_SCALE = 1.000
78+
MIN_LIMIT = -40.0
79+
MAX_LIMIT = 40.0
80+
FERROR = 0.050
81+
MIN_FERROR = 0.010
82+
83+
[JOINT_2]
84+
TYPE = LINEAR
85+
HOME = 0.0
86+
MAX_VELOCITY = 4
87+
MAX_ACCELERATION = 1000.0
88+
BACKLASH = 0.000
89+
INPUT_SCALE = 4000
90+
OUTPUT_SCALE = 1.000
91+
MIN_LIMIT = -4.0
92+
MAX_LIMIT = 4.0
93+
FERROR = 0.050
94+
MIN_FERROR = 0.010
95+
96+
[EMCIO]
97+
TOOL_CHANGE_QUILL_UP = 1
98+
RANDOM_TOOLCHANGER = 0
99+
TOOL_TABLE = sim.tbl

0 commit comments

Comments
 (0)