feat(rs274ngc): add ROTARY_MODULO axis mode - #3969
Conversation
|
If this lands, future work I see worth tracking:
Happy to take any of these as follow-up PRs if there is interest. |
|
Does this affect G1 moves? I think people would be surprised if a G1 move didn't do exactly what it was told to do... |
I think it would be even more confusing having G0 act differently from G1, it is an opt in configuration, user should expect changes, when enabling option for modulo motion for an axis, I'm not clear as to why it should be G0 only, that makes it more confusing, a clear flag, that axis works modulo, G0 and G1 is more sensible, and similar to what commercial counterparts do. |
|
Because the common case is (at least in my experience) that you do a lot of G1 milling moves and the rotary axis "winds up" the angle (I've seen it in the hundreds of thousands of degrees). At the end of the job (or start of the next operation) there's a G0 A0 to reset the rotary, and it takes many minutes even at rapid RPMs. What the user really wants is to do all the winding up according to plan, and at the end just move as quickly as you can to the angle requested (i.e. always less than 360 degrees of actual motion). |
|
How about you try it? I don't think I changed G1 behavior in a way of which you will disapprove, test and see |
|
You know how to download the .deb from GitHub? |
|
Absolute moves take shortest path, and accept numbers over 360 or below -360, your small G1 moves always want the shortest path, and so do your G0 moves, there is no distinction or different behavior needed to solve your issue, shortest path is the valid wanted behavior in both cases |
Sorry, I did not explain well, yes it does effect G1 moves, but ONLY absolute moves (G90), and only those moves that require the axis to move more than 180 degree, example all of the above no change The above type moves ONLY have changed, and take the shortest path moving backward in respect to what was programmed, A axis would move -170 incrementally from A2000 ending up on A1830 in the joint position. |
|
I'll try it when I get a chance, sure. I was worried about commands like "G1 X5 A7200" to do a simple rotary spiral flattening, for example, with a "G0 A0 X0" to return. If that G1 didn't go around 20 times the result would be incorrect. |
|
You can use G91 for the special cases where you need multiple turns, I only modified G90 behavior |
|
Hmm... if I was willing to generate modulo g-code, I would have just use WRAPPED_ROTARY. I think anything that changes what G1 does is going to be problematic, and I wouldn't have modified G1 at all. Ideally, no change to gcode should be needed. |
|
Fair concern, let me be straight about where I land. I will add M26/M27 to this PR as a follow-up commit: M26 enables shortest-path on modulo axes (the default when That is the ground I am willing to give. I do not want to split G0 and G1 under the same flag, and I looked for commercial precedent before saying that. Siemens 840D in modulo mode treats absolute as shortest for both G0 and G1, with per-block overrides like I do understand this asks users with existing G-code to adapt if they turn the flag on, but the flag is opt-in and off by default, and I think the behavior is useful and intuitive for most people who would reach for it. This is LinuxCNC, not any one user's machine, and a feature that aligns with how Siemens, Heidenhain, and Fanuc handle rotary modulo seems worth having available. I will push the M26/M27 commit shortly. If you try the .deb after that, feedback welcome. |
Modal pair (group 3) for absolute moves on axes flagged ROTARY_MODULO=1: M26 selects shortest-path (default), M27 forces literal absolute target so multi-turn winding written in G90 is honored. Per-block override matches Heidenhain M126/M127 semantics without splitting G0/G1 behavior. - New rotary_modulo_literal setup flag, gated in interp_find.cc shortest-path callsites (find_ends + find_relative) - ems[26]=ems[27]=3, STEP_M_3 enum, convert_m handler - Saved/restored by M70/M72/M73 via active_m_codes[9] and gen_m_codes case 9 - Parameter readout (#5423-#5425) unaffected; remains wrapped - Docs in m-code.adoc and ini-config.adoc Refs LinuxCNC#3969
|
Updated M27 semantics in the latest commit. The original M27 (literal multi-turn absolute) had an unsafe entry condition: with accumulated Closing that hole would have required an additional reset primitive (M94-style rebase of Redesigned M27 to instead modulo the input mod 360 and use the sign of the input for direction:
This matches Heidenhain M127 default and Siemens ACP/ACN per-block intent on a modulo axis. Multi-turn motion (helical winding, wire wrapping) is now exclusively the domain of Net: foot-cannon eliminated by construction, no reset machinery needed, smaller PR scope, cleaner mapping to industry semantics. Docs in |
|
Where are we at with this PR? The OP seems to have lost interest, but it looks like something worth having. |
|
I haven't lost interest, I just haven't yet had time to test it. |
|
I don't have a machine to test this, and since it's mostly in my head, and I already screwed it once, it has to be tested before merge, just waiting on that... |
|
I have the hardware so I can do testing. I'll report back. |
|
Works for me on real hardware as described in the documentation. This implementation is clearly not as easy to use as the 'G1 does multi turn' , 'G0 does shortest move' logic that was envisioned by the OP.
|
|
You should test #3990 as well then, that should be OP original ask |
While certainly a more direct solution for the OP's use case, I somewhat dislike having the interpreter using user accessible offsets like that. So right now I would tend to favor the |
|
Ok then, opening this to review, I guess ready to merge... |
|
Pushed a fix on top of what you tested. M27 took its direction from the value after offsets were subtracted, so on an axis with a G54 rotary offset a I also inverted the startup limit warning. It complained about a range that is not ~360 deg, but ~360 is the range that cannot work: the commanded position accumulates, so motion is refused once it passes M26 output is unchanged from what you tested, so your results should still hold. If you have the machine handy, the only new ground is M27 with a G54 A offset active: |
Modal pair (group 3) for absolute moves on axes flagged ROTARY_MODULO=1: M26 selects shortest-path (default), M27 forces literal absolute target so multi-turn winding written in G90 is honored. Per-block override matches Heidenhain M126/M127 semantics without splitting G0/G1 behavior. - New rotary_modulo_literal setup flag, gated in interp_find.cc shortest-path callsites (find_ends + find_relative) - ems[26]=ems[27]=3, STEP_M_3 enum, convert_m handler - Saved/restored by M70/M72/M73 via active_m_codes[9] and gen_m_codes case 9 - Parameter readout (#5423-#5425) unaffected; remains wrapped - Docs in m-code.adoc and ini-config.adoc Refs LinuxCNC#3969
32c8360 to
59f67fb
Compare
fc988bd to
aa46a39
Compare
[AXIS_<L>] ROTARY_MODULO = 1 makes the axis continuous-modulo: absolute words of any magnitude are accepted and reduced mod 360, while the internal commanded position and motion-side HAL pins stay accumulated so stepgens, encoders and PID loops see no phantom unwind. #5423-5425, #5064-5066 and the named position parameters report the wrapped angle; the accumulated position remains readable via #<_hal[joint.N.pos-fb]>. M26 (default) takes the shortest path, at most 180 degrees, ties broken negative. M27 approaches the wrapped angle in the direction selected by the sign of the word; a value that wraps to the current angle moves nothing. Moves to stored positions (G28/G30, tool change) always take the shortest path. G91 is unaffected and remains the way to command multi-turn motion. Mutually exclusive with WRAPPED_ROTARY (startup warning, WRAPPED_ROTARY wins). Threading words (G33/G33.1/G76) on a modulo axis are a hard error.
aa46a39 to
cc2c22d
Compare
ini-config: ROTARY_MODULO entry in the [AXIS_<L>] section. m-code: M26/M27 section with usage example, the no-motion behavior when a word wraps to the current angle, and the G91 multi-turn idiom. overview: modal group table entry for group 3.
cc2c22d to
7573ef1
Compare
|
Fancy simulations! I like it. |
Summary
Continuous-modulo rotary mode for A/B/C axes. Absolute moves take shortest path, large literals (e.g.
A=200000) accepted, position parameters wrapped to 0 up to but not including 360 degrees. Internal commanded position and motion-side HAL pins remain accumulated to keep stepgens, encoders and PID loops consistent across wrap, per @andypugh's note in #3902.Closes #3902.
Behavior
[AXIS_<L>] ROTARY_MODULO = 1, mutex withWRAPPED_ROTARYMIN_LIMIT/MAX_LIMITrange is not ~360 degfind_endsshortest-delta target on G53 + absolute + relative paths#5423-#5425,#5064-#5066,#<_a/_b/_c>,#<_abs_a/b/c>wrapped on read#<_hal[joint.N.pos-fb]>Out of scope
Test plan
ROTARY_MODULO=1, run program that drives A to large value thenG0 A0, verify motion is ~residual angle not full unwind#5423reads wrapped, HAL pin reads accumulatedWRAPPED_ROTARY=1+ROTARY_MODULO=1G33 A...with modulo AWRAPPED_ROTARY=0(default) unchangedWRAPPED_ROTARY=1unchangedIn action