G28 with features#4172
Conversation
Add two non-modal (group 0) G-codes to trigger the machine homing cycle from G-code, so a machine can reference / clear references from MDI or a program instead of only from the GUI: G28.2 run the homing cycle (all joints, in HOME_SEQUENCE order) G28.3 unhome (all joints) - interp: enum G_28_2/G_28_3, modal group 0, accepted in check_g_codes; convert_modal_0 -> convert_home_cycle (cutter-comp guard) - canon: HOME_CYCLE()/UNHOME_AXES() -> EMC_JOINT_HOME/UNHOME(joint=-1); saicanon/gcodemodule stubs Bare form only (no axis words). Useful for unattended power-up and for operators who prefer a typed reference command.
EMC_JOINT_HOME_TYPE and EMC_JOINT_UNHOME_TYPE were missing from emcTaskCheckPreconditions(), which is called for every command pulled off the interp_list. A homing command that arrives via the queue (e.g. from a G-code like G28.2, or any front-end that queues it) therefore hit the 'default' case and returned EMC_TASK_EXEC::ERROR - the command was dropped and never reached motion. Add both types returning WAITING_FOR_MOTION (drain prior motion, then home). Bug fix; independent of the G28.2/G28.3 codes (any queued home benefits).
EMCMOT_JOINT_HOME required motion_state == FREE. Allow it also when motion is otherwise idle (in position, queue empty) so a homing command issued from MDI or a program (G28.2) is honored, while still refusing to home mid-motion. No change when already in free mode.
…_HOMING=1) With [RS274NGC]GCODE_HOMING=1 (default 0 = stock), a plain G28 runs the machine homing cycle before its natural return move whenever the machine is not already fully homed; a fully-homed machine sees a pure legacy G28 (return only). G30 and G28.2/G28.3 are unchanged. Lets a machine reference itself from MDI or from the top of a program (e.g. unattended power-up) instead of only from the GUI, while a homed machine pays nothing. Flow: interp convert_home (FEATURE_GCODE_HOMING + G_28) emits a new canon op HOME_CYCLE_IF_UNHOMED() before the waypoint/return moves. Canon queues EMC_JOINT_HOME carrying the EMC_HOME_ALL_IF_UNHOMED (-3) sentinel in its 'joint' field. Task resolves the sentinel at execution time: if all_homed() the home is dropped (the queued return alone = pure legacy G28), otherwise it issues the normal home-all (emcJointHome(-1)) - the same path G28.2 and the GUI Home-All already use. No new command field, no motion / homing.c / NML-layout change. Single-channel; built on the G28.2/G28.3 home-cycle G-codes. Verified at the interpreter (rs274 -i): GCODE_HOMING=1 plain G28 emits HOME_CYCLE_IF_UNHOMED() before the return traverse; G30 does not home; G28.2 still homes unconditionally; default-off G28 is bit-identical to stock (no homing emitted). Full build (interp/task/motion) clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Would it be possible to add a parameter for homing individual joints? Example:
This would be very useful for configurations with joints that switch between rotary and spindle use. It would also circumvent #3556 that complicates the current way of 'rehoming' |
|
Home individual axis- G28.2XC will force home axis X and C ... for non trivial kinematics we need to start discussion how to handle it per joint.. |
|
What happens if we try to run a program in unhomed state ( will that trigger an interpreter error?): Example 1 : How are these commands handled when used inside a gcode program? (I presume it is like a queue buster command that halts the read ahead until all queued command have been executed) : Example 2 : |
|
Example 1 : Example 2 : |
Using axes is probably enough for the majority of use cases and most machine operators would likely not even know about the joint-axis mappings on their particular machines. |
|
I think the cleanest direction is to keep the G-code surface dead simple and put the real effort into execution. For per-joint homing, Sigma's The part that really needs rethinking isn't the syntax, it's how a queued home executes. Homing only runs in free mode, and nothing currently flips the machine into free for a G-code-triggered home, so just relaxing the motion guard means the command can silently stall in teleop. It needs to be sequenced in task: drain motion, switch to free, home, wait for it to actually finish, then restore the prior mode. And if homing fails, the program has to abort rather than carry on unreferenced. A nice consequence is the trivkins question answers itself: home-all works everywhere, but a partial home can only resume coordinated motion on identity kinematics, because non-trivkins won't re-enter teleop until everything's homed. There's also the unhome-then-keep-running hole Sigma raised. The existing force-homing check only fires at program start, so Given all that, I'd split it: land the explicit |
Document the G-code machine-homing feature and add interpreter-level regression tests for it. Docs: - g-code.adoc: new "G28.2, G28.3 Home, Unhome from G-code" section, a GCODE_HOMING note in the G28 section, and a quick-reference entry. - ini-config.adoc: GCODE_HOMING entry in the [RS274NGC] section. Tests (tests/interp/gcode-homing, rs274 canon-level): - homing-on: with [RS274NGC]GCODE_HOMING=1, a plain G28 emits HOME_CYCLE_IF_UNHOMED() before its return; G28.2 -> HOME_CYCLE(), G28.3 -> UNHOME_AXES(). - homing-off: default (flag off) a plain G28 emits no homing op, while G28.2/G28.3 still home/unhome (flag-independent). Verified: new tests pass; tests/interp + tests/abort = 86/86 (1 skipped), build clean. Co-authored-by: Luca Toniolo <10792599+grandixximo@users.noreply.github.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
G-code machine homing: G28.2 / G28.3 and optional GCODE_HOMING for plain G28
What this is
Adds the ability to reference (home) a machine from G-code, instead of
only from the GUI, in three small, opt-in pieces:
G28.2— run the homing cycle on all joints (inHOME_SEQUENCEorder)G28.3— unhome all joints[RS274NGC]GCODE_HOMING=1(INI opt-in) — a plainG28references themachine first, before its normal return move, only when the machine is
not already fully homed
Plus two small fixes that make a queued (in-program / MDI) home actually
reach motion (see below).
G28.2/G28.3are non-modal (modal group 0) codes, following theexisting
G28.1/G30.1pattern. Bare form — axis words are ignored; theyact on all joints.
What it's for
the machine, so an operator (or an automation layer) doesn't have to open
the GUI and click Home All.
GCODE_HOMING=1lets you put a plainG28at the top of a program: on acold machine it homes first, then returns; on an already-homed machine it
is a pure return move and costs nothing.
Relation to industrial-standard G28
G28return-to-reference behavior is unchanged and still matchesthe Fanuc/Haas convention: go to the machine reference point through the
intermediate point given by the axis words.
GCODE_HOMING=1makes the firstG28after power-up also establishthe reference (run the homing cycle), which mirrors how a Fanuc-style
control without absolute encoders performs its zero-return/reference on a
G28. Once referenced, subsequentG28s are pure returns, exactly as onthose controls.
G28.2/G28.3(explicit home / unhome) are LinuxCNC extensions — thereis no standard Fanuc equivalent — kept in the spirit of the existing
G28.1/G30.1reference-point codes.[RS274NGC]GCODE_HOMING=1— behaviorG28does=0(default)=1, machine not fully homed=1, machine fully homed=1,G30/G28.2/G28.3G28-only)Default-off is bit-identical to stock: the homing call is only emitted under
FEATURE(GCODE_HOMING)forG_28.How it works (single channel)
interpconvert_home: underFEATURE_GCODE_HOMINGandmove == G_28,emit a new canon op
HOME_CYCLE_IF_UNHOMED()before the waypoint /return moves (so it completes while joint positions are still unknown).
canonqueuesEMC_JOINT_HOMEcarrying anEMC_HOME_ALL_IF_UNHOMED(
-3) sentinel in its existingjointfield.taskresolves the sentinel at execution time: ifall_homed(), drop thehome (queued return alone = legacy
G28); otherwise issue the normalhome-all (
emcJointHome(-1)) — the same pathG28.2and the GUI HomeAll already use.
The sentinel mechanism itself adds no new message field and no NML-layout
change, and touches neither
homing.cnor the motion command path — itresolves entirely in
taskby reusing the existingjointfield with areserved value. (The small
command.cidle-homing fix below is a separateprerequisite, shared with
G28.2.)Supporting fixes (also needed for
G28.2)EMC_JOINT_HOME_TYPE/EMC_JOINT_UNHOME_TYPEwere missing fromemcTaskCheckPreconditions(), so a queued home/unhome hit thedefaultcase and was silently dropped before reaching motion. They now return
WAITING_FOR_MOTION(drain prior motion, then home).motion_state == FREE; now it isalso permitted when motion is otherwise idle (in position, queue empty), so
a home issued from MDI or a program is honored. Refusing mid-motion still
holds.
Testing
rs274 -i):GCODE_HOMING=1plainG28emitsHOME_CYCLE_IF_UNHOMED()ahead of the return traverse;G30does not home;G28.2homes unconditionally; default-offG28emits no homing.program) is pending and will be added.
Credits
Developed in collaboration with @grandixximo, with whom I discussed the requirements that
shaped this feature. Thanks for the design discussion and for driving the
real-world G28 / homing-from-G-code use case.