LinuxCNC / linuxcnc

LinuxCNC controls CNC machines. It can drive milling machines, lathes, 3d printers, laser cutters, plasma cutters, robot arms, hexapods, and more.
http://linuxcnc.org/
GNU General Public License v2.0
1.78k stars 1.14k forks source link

stat.gcodes out of sync with parameter[5220] -> wrong DRO read out #2745

Open Sigma1912 opened 10 months ago

Sigma1912 commented 10 months ago

I'm reissuing this one with a clear description:

Using a recent build of version 2.9.1

  1. Start the 'axis' sim config
  2. Home the machine
  3. Load an .ngc like this one:
    g10 l2 p2 x1
    g55
    g0 x10
    m2
  4. Run the above gcode
  5. We get an error message about limit violations which is to be expected however stat.gcodes (used to display the 'Active G-Codes') and the value of parameter[5220] (which I presume is used for the DRO) are now out of sync:

axis_out_of_sync

My reaction would now be to simply dismiss the 'Active G-Codes' and argue that the DRO is what counts. However:

  1. Run MDI command: 'G0 X0'
  2. If the DRO were correct we would expect the x axis to move from ' X: -1.0000' to 'X: 0.0000' but nothing changes.
  3. Run MDI command: 'G0 X1'
  4. Instead of moving to X : 1.0000 the DRO changes from' X: -1.0000' to 'X: 0.0000'

Note: Running 'M2' in MDI will put things right, so I presume that due to the limit error while trying to run the gcode the 'm2' in the code is not executed. It seems that an error during gcode execution will reset the stat.gcodes to G54 but not parameter[5220].

Sigma1912 commented 10 months ago

In Gmoccpy the DRO follows stat.gcodes but the DRO values are also out of sync with MDI commands just like in axis:

gmoccapy_out_of_sync

Sigma1912 commented 10 months ago

Closed until I come up with a better bug description

Sigma1912 commented 10 months ago

Reopened with a clear bug description

Sigma1912 commented 10 months ago

Workaround:

With this in the [RS274NGC]-section of the ini:

ON_ABORT_COMMAND = o call

and this in the on_abort.ngc:

o<on_abort> sub
;Workaround for 
;https://github.com/LinuxCNC/linuxcnc/issues/2745
;https://github.com/LinuxCNC/linuxcnc/issues/2908
;store current offset index
#1 = #5220 
; we must switch through at least 3 indexes
G56
G55
G54
; restore the index from above
o101 if [#1 GT 6]
(print, Code [#1-6])
 G[59+[#1-6]/10]
o101 else
 G[53+#1]
o101 endif
;(msg, on_abort sub executed)
o<on_abort> endsub
m2

Notes:

[Edit] Actually we need to switch to an offset-index that is not G54 AND not the one set before the abort. Hence we switch through three indexes and then restore the index active at the beginning.

+ m2 in oword

https://linuxcnc.org/docs/devel/html/remap/remap.html#cha:remap

rmu75 commented 9 months ago

It seems that an error during gcode execution will reset the stat.gcodes to G54 but not parameter[5220].

How did you check the parameter?

I think the "current" WCS is somewhat poorly defined in the interpreter. For reasons of path optimization, the interpreter is running way ahead of where the machine is, so the GUI has to look at the state tags of the motion currently executing. If there is no motion happening then it's (probably) the EMC_STAT where info comes from. Maybe in this error case some event that DRO / backplot needs updating is lost (in the GUIs), but it may also be possible something else is at fault.

Sigma1912 commented 9 months ago

How did you check the parameter?

Basically what I found is:

sometimes 'self.stat.gcodes' disagrees with 'self.status.g5x_index' and it seems 'self.status.g5x_index' reflects parameter[5220] while 'self.stat.gcodes' gets updated in some other way.

When this happens the position values in the DRO do not reflect the internal state anymore.

Background:

The reason I came across this behavior is that I wanted to use emccanon. commands in a python remap to change the current WCS like this:


                self.params[5220] = 9
                emccanon.SET_G5X_OFFSET(
                    100,
                    0,
                    0,
                    0,
                    0,
                    0,
                    0,
                    0,
                    0,
                    0,
                )
                yield INTERP_EXECUTE_FINISH

What I noticed is that in AxisGUI the DRO will change the WCS to 'G59.3 ' (ie 9) however the Active Gcodes (ie stat.gcodes) is not updated to the new WCS (ie it does not change to 'G59.3').

In Gmoccapy the WCS index in the DRO follows the one in 'Active GCodes' so I investigated this line 247 in 'combi_dro.py' (used in gmoccapy):

    self.gstat.connect('user-system-changed', self._user_system_changed)

which is indeed executed when the above emccanon. command runs and eventually executes this code that uses status.gcodes to display the current WCS:

    # get the actual coordinate system to display it on the DRO
    def _get_current_system(self):
            gcode = self.status.gcodes[1:]
            for code in gcode:
                if code >= 540 and code <= 590:
                    return "G%s" % int((code / 10))
                elif code > 590 and code <= 593:
                    return "G%s" % int((code / 10.0))
            return "Rel" 

So basically 'Gstat' correctly sends the message that there has been a change in the WCS system but because this change is not reflected in self.status.gcodes the DRO does not change.

Note that if we use 'status.g5x_index' in the above code:

       code = self.status.g5x_index

the Gmoccapy DRO will then also disagree with the 'Active Gcodes' which leads me to presume that 'status.g5x_index' reflects the state of parameter[5220].

Only later did I realize that this state can also occur when not using python remaps and when this occurs that the position in the DRO in both Axis and Gmoccapy and likely all the other Guis is also wrong.

Unfortunately I'm usually quickly lost as soon as C/C++ code is involved which seems to be where the 'status' channel is coming from.

rmu75 commented 9 months ago

IIRC 'self.stat.gcodes' comes from motion state tags, and that is only valid while some sort of motion is happening.

The whole code around that is kinda messy and has probably bugs. On the gui side some unification is needed, now there are too many parallel implementations of basic logic which are (probably) slightly different.

Sigma1912 commented 6 months ago

Looking at this, it seems to me that parameter values may only get updated through gcodes (and m2?):

parameters_set_by_gcode

Is this correct? Which would maybe explain why a reset on abort would leave the parameter values out of sync with the system

On the other hand we have two 'SET_G5x_OFFSET' functions: set_g5x_offset

Is one of these where the 'self.stat' tags come from? If so what is the other?

Sigma1912 commented 6 months ago

If there is no motion happening then it's (probably) the EMC_STAT where info comes from.

Not sure if that is what you meant by 'EMC_STAT' but it's not coming from 'emcStatus->task.g92_offset.tran.x' (I can change that value in halui.cc and the DRO does not change it's behavior at all)