Flex Gui forces machine into Manual mode when any other process switches to MDI

More
17 Nov 2024 02:21 #314636 by digiex_chris
Hi there,

I'm setting up some surface grinder automation for some use cases where calling subroutines isn't quite dynamic enough (hal parameters change mid-job ), so being able to override things with my own python has been immensely helpful! I have discovered a problem unrelated to that though, this is reproduceable without importing any python. It happens when loading a custom hal module and the module, unaware of flexgui, issues MDI commands.

I am running multiple MDI commands in a different process that is triggered by HAL pins. Flexgui is switching the hal state in order to manage the background process. That part is working great.

It seems that flexgui has some code that watches the interp state, and if an MDI command is done, switches the task state back into MANUAL. My first command sets it into MDI mode, executes one MDI command, executes a second, waits until it's complete, and then the loop restarts. By the time the second loop iteration starts setting the MDI mode, it seems that flexgui is attempting to switch the mode from MDI back to Manual. Even if I switch it to MDI again before each MDI command, flexgui has switched it back to manual before my next MDI command can run. Future loop iterations, even though they switch to MDI mode at the beginning of the loop, don't stay in MDI mode before the next line runs.

This doesn't occur for any MDI commands sent via the UI thread, I assume because it's happening within the same update frame as flex is running in, so everything happens sequentially. That or the race condition has a longer time interval, so less of a chance for it to happen. It's very easy to make it happen when there are multiple processes or threads however.

I've narrowed it down to these lines in the below commit, removing it makes this all work, and preserves the functioning of the MDI tab along with it's history, but I'm not sure what implications this might have on anything else that flexgui is doing with it.
github.com/digiexchris/flexgui/commit/9f...d882032d85a41f7968d3

A minimal reproducable example would be this:
github.com/digiexchris/qtpyvcp_grinder_t...der_touch/process.py
and place the following at the end of your main hal file:
loadusr python3 process.py

It will delay the loop by 10 seconds in order for you to clear estop, set the machine to on, and home it.

Then the console you started linuxcnc in should start to give you the following output, and does using Touchy and Axis:

Loop
Current mode: Manual
Current mode: MDI
Current mode: MDI
Current mode: MDI
Loop
Current mode: MDI
Current mode: MDI
Current mode: MDI
Current mode: MDI
Loop
Current mode: MDI
Current mode: MDI
Current mode: MDI
Current mode: MDI
Loop
Current mode: MDI
Current mode: MDI
Current mode: MDI
Current mode: MDI
Loop
Current mode: MDI
Current mode: MDI
Current mode: MDI

and you can watch the X coordinate in the UI oscillate between X1 X2. 

In Flex, 

Loop
Current mode: Manual
Current mode: Manual
Must be in MDI mode to issue MDI command
Current mode: Manual
Must be in MDI mode to issue MDI command
Current mode: Manual
Loop
Current mode: Manual
Current mode: Manual
Must be in MDI mode to issue MDI command
Current mode: Manual
Must be in MDI mode to issue MDI command
Current mode: Manual
Loop
Current mode: Manual
Current mode: Manual
Must be in MDI mode to issue MDI command
Current mode: Manual
Must be in MDI mode to issue MDI command
Current mode: Manual

Occasionally you do see it go into MDI for one iteration, but flex is usually pulling it into manual pretty quickly. For some reason, When I control the loop with a HAL pin, which is changed by flexgui, the first iteration of the loop works, and subsequent ones fail with the above reasoning. But I suspect that's just a side effect of the GSTAT polling and handlers slowing the UI thread down enough for the first loop iteration to work.
 
Any suggestions? Auto mode doesn't work because I can't have the interpreter load the entire gcode program from the start, it's generated as the job progresses, kinda like how gcode is streamed to a 3d printer. Ideally I'd prefer if this behaviour matched Axis and Touchy (who have intentionally maintained the ability to execute multiple MDI commands sequentially with one mode switch)

Please Log in or Create an account to join the conversation.

More
18 Nov 2024 12:19 - 18 Nov 2024 12:20 #314747 by JT
Thanks for the example file that helped a lot to narrow down where the mode change was taking place. Your program now works without changing modes and MDI commands in Flex work as expected.

JT
Last edit: 18 Nov 2024 12:20 by JT.
The following user(s) said Thank You: tommylight, digiex_chris

Please Log in or Create an account to join the conversation.

More
18 Nov 2024 17:38 #314777 by digiex_chris
Wow, that's incredibly fast! Thank you!

Please Log in or Create an account to join the conversation.

More
19 Nov 2024 21:41 #314877 by digiex_chris
I gave it a try today, and with my example script it's behaving better, but if you speed the loop up, it still shows up. This is with the following loop:
while True:
        print("Loop")
        print_mode()
        c.mode(linuxcnc.MODE_MDI)
        c.wait_complete()
        print_mode()
        c.mdi("G1 X0.1 F1000")
        c.wait_complete()
        print_mode()
        c.mdi("G1 X0.2 F1000")
        c.wait_complete()
        print_mode()
        time.sleep(0.1)

as you can see below, there is still something checking and reverting back to manual mode in between commands.
I have a branch set away with a sim config for my actual project I'm setting up that this bug reproduces with the actual UI I've been playing with, if if that helps (VERY work in progress :D ): github.com/digiexchris/qtpyvcp_grinder_t...ee/flexhal-mdi-issue
should be able to cd into rpi_grinder_touch and execute linuxcnc ./rpi_grinder_touch.ini and it should run it for you. Just take it out of estop, power on, and hit run. homing is optional to duplicate the issue. the script that's running as a loadusr module is in grinder-backend.py

Loop
Current mode: Manual
Current mode: MDI
Current mode: MDI
Current mode: Manual
Loop
Current mode: Manual
Current mode: MDI
Current mode: MDI
Current mode: MDI
Loop
Current mode: Manual
Current mode: MDI
Current mode: MDI
Current mode: Manual
Loop
Current mode: Manual
Current mode: MDI
Current mode: MDI
Current mode: MDI
Loop
Current mode: Manual
Current mode: MDI
Current mode: MDI
Must be in MDI mode to issue MDI command
Current mode: Manual
Loop
Current mode: Manual
Current mode: MDI
Current mode: MDI
Current mode: MDI
Loop
Current mode: Manual
Current mode: MDI
Current mode: MDI
Current mode: Manual
Loop
Current mode: Manual
Current mode: MDI
Current mode: MDI
Current mode: MDI
Loop
Current mode: Manual
Current mode: MDI
Current mode: MDI
Must be in MDI mode to issue MDI command
Current mode: Manual
Loop
Current mode: Manual
Current mode: MDI
Current mode: MDI
Current mode: MDI
Loop
Current mode: Manual
Current mode: MDI
Current mode: MDI
Must be in MDI mode to issue MDI command
Current mode: Manual
Loop
Current mode: Manual
Current mode: MDI
Current mode: MDI
Current mode: MDI
Loop
Current mode: Manual
Current mode: MDI

Please Log in or Create an account to join the conversation.

More
20 Nov 2024 12:16 - 20 Nov 2024 12:17 #314898 by JT
I get errors when I try and run it and the run button does nothing for me.

john@cave:~/qtpyvcp_grinder_touch/rpi_grinder_touch$ linuxcnc ./rpi_grinder_touch.ini
LINUXCNC - 2.9.2-64-g675988daf7
Machine configuration directory is '/home/john/qtpyvcp_grinder_touch/rpi_grinder_touch/.'
Machine configuration file is 'rpi_grinder_touch.ini'
Starting LinuxCNC...
linuxcnc TPMOD=tpmod HOMEMOD=homemod EMCMOT=motmod
Note: Using POSIX realtime
Found file(REL): ./sim.hal
Grinder hal ready
GRINDER_BACKEND STARTED
/home/john/qtpyvcp_grinder_touch/rpi_grinder_touch/./rpi_grinder_touch.ini:49: executing 'import sys
sys.path.insert(0,"python")'
PythonPlugin: Python '3.11.2 (main, May 2 2024, 11:59:08) [GCC 12.2.0]'
/home/john/qtpyvcp_grinder_touch/rpi_grinder_touch/./rpi_grinder_touch.ini:49: executing 'import sys
sys.path.insert(0,"python")'
PythonPlugin: Python '3.11.2 (main, May 2 2024, 11:59:08) [GCC 12.2.0]'
is_callable(remap.queuebuster) = TRUE
is_callable(__init__) = FALSE
Stopping BE
Could not parse stylesheet of object flexgui(0x16103a0, name = "MainWindow")
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/libflexgui/startup.py", line 1798, in setup_import
module = importlib.import_module(module_name)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/importlib/__init__.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<frozen importlib._bootstrap>", line 1206, in _gcd_import
File "<frozen importlib._bootstrap>", line 1178, in _find_and_load
File "<frozen importlib._bootstrap>", line 1149, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 690, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 940, in exec_module
File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
File "/home/john/qtpyvcp_grinder_touch/rpi_grinder_touch/grinder.py", line 4, in <module>
from qtpy.QtWidgets import QLineEdit, QPushButton, QComboBox, QDoubleSpinBox, QSpinBox, QCheckBox, QWidget
ModuleNotFoundError: No module named 'qtpy'

Could not parse stylesheet of object flexgui(0x16103a0, name = "MainWindow")
task: main loop took 0.131505 seconds
Shutting down and cleaning up LinuxCNC...
task: 10460 cycles, min=0.000006, max=0.131505, avg=0.010063, 1 latency excursions (> 10x expected cycle time of 0.010000s)
is_callable(__delete__) = FALSE
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/gi/_ossighelper.py", line 92, in signal_notify
def signal_notify(source, condition):

KeyboardInterrupt
Note: Using POSIX realtime
john@cave:~/qtpyvcp_grinder_touch/rpi_grinder_touch$


JT
Last edit: 20 Nov 2024 12:17 by JT.

Please Log in or Create an account to join the conversation.

More
20 Nov 2024 12:46 #314902 by JT
There's one place in status.py line 138 that sets the mode to manual after a mdi and the interp is idle...

JT

Please Log in or Create an account to join the conversation.

More
20 Nov 2024 12:55 #314903 by JT
I've changed it so an internal MDI button resets the mode but external MDI should not.

JT

Please Log in or Create an account to join the conversation.

More
20 Nov 2024 19:45 #314936 by digiex_chris
Thanks, that works perfectly!

Yes it seems I have mistakenly used qtpy instead of PyQt6, and so needs qtpy installed. I'll align with flexgui on QT6.

Please Log in or Create an account to join the conversation.

Time to create page: 0.081 seconds
Powered by Kunena Forum