task: reset canon length units on program open (fixes #4194)#4196
task: reset canon length units on program open (fixes #4194)#4196grandixximo wants to merge 1 commit into
Conversation
G20/G21 from a previous run persists in canon.lengthUnits, causing FROM_PROG_LEN() to convert differently on re-run for G-code commands that appear before the G20/G21 line. This shows up as wrong unit scaling (off by 25.4x) on the lead-in moves of the second run, producing jagged velocity in the scope. Reset canon.lengthUnits to the machine default in emcTaskPlanOpen before reopening the interpreter. Fixes LinuxCNC#4194
|
Are there other machine state issues when opening a new file? |
|
Good question, it goes to the heart of it. Let me give the concrete mechanism first, then the options, because I think this is a direction call more than a one-line fix. The trigger is in the gcode:
So the run-to-run difference is the init-versus-open asymmetry: machine state is re-established to native at To your actual question, are there other machine state issues on opening a new file: yes, structurally. Granted the gcode is malformed: units should precede any unit-dependent word, and every controller documents the safe-start line for exactly this reason. But even malformed gcode should run the same way on every run, and right now it does not. That inconsistency is the part I would not want to leave as is, independent of whose fault the gcode is. A few directions, and I would like your read:
My own lean is option 1 as the baseline, since it gives consistent behavior with the least disruption and matches the existing boot-to-native model, with option 2 available if retained units are wanted. But you or @andypugh might have a better sense of the historical intent here, so I would rather hear which way you think it should go before I expand the PR. |
|
There are three things that come in mind (probably more):
The real question that needs to be answered is what the user expects at 3 and what we are supposed to provide. The first and second are normally deterministic afaik. However, there is bleed-over into 2 from running a program. What is "session modal" in the context of just having run a program? Even re-running the same program can result in disaster when you switch units in the middle and don't reset to the previous state. Bad, program code, yes, but should that error plow through your machine? For a "quick fix", you could restore the session modal state after a program finishes. That would prevent you from "seeing" what exact state the program ended in. But any new run, same or new program, would always see the same state. |
|
The way I read the report now: the bug isn't that the second run is rough, it's that malformed gcode doesn't run consistently bad. Frame it that way and holding the state is the fix, not resetting it. That's my shift, and it's why I land opposite to restoring session modal on stop or end. Persistence is what every other control does and what an experienced operator expects. The modal state, above all the active WCS and offsets but units too, is set deliberately and relied on staying put. Resetting it out from under the operator after a program ends is its own surprise and its own crash class, and no other control sandboxes a run this way. On what "session modal" is after a program: the program's end state is the new session state. That's the model on Fanuc and the rest; the operator knows what they ran and what it left active. On the safety case: a program that flips units mid-run and is re-run from a stale state is bad gcode, and the guard against it is the safe-start line that every post already uses. Having the controller silently reset deliberately-set state to defend against malformed programs trades a rare, self-inflicted problem for a common surprise. Better the bad program run wrong consistently, like on any other control, so the lesson is the usual one: declare your modals at the top. The defect here exists only because state is re-established to native at startup ( Do you or @andypugh see a reason the historical reset-to-native-at-startup should win over matching the persistence every other control provides? If retain is the agreed direction I'll reshape the PR toward saving and restoring the unit state rather than resetting it. |
Note that we have just added an opt-in setting to persist the WCS: #4093
|
Root cause
canon.lengthUnits(inemccanon.cc) is module-global and is only updated when the interpreter emitsUSE_LENGTH_UNITS, i.e. when it reaches a G20/G21. It is never reset when a program is reopened. So on a re-run, the program-open and setup conversions that happen before the units word are done with the previous run's units (off by 25.4x), while the first run used the machine default.That difference is small, but it perturbs the entry velocity into the first segments. On the S-curve planner the short-tangent ramp/no-ramp decision is sensitive to the live entry velocity (see the analysis in #4194), so the perturbation flips borderline segments and cascades through the rest of the run. The net effect is that the entire second run commands a different, rougher velocity profile than the first, even though the G-code is identical.
Fix
Reset
canon.lengthUnitsto the machine default inemcTaskPlanOpen()before reopening the interpreter, so every run starts from the same canon unit state:Testing
axis_mm_scurve, PLANNER_TYPE=1, dense micro-segment file: before the fix the 2nd+ runs are rough; after the fix every run matches the first.@greatEndian I believe this is the source of the run-to-run difference. Could you test it against your
axis_mm_scurvedense micro-segment file and confirm both the rerun roughness and any long-run degradation are gone for you?Fixes #4194