Liveplotter error - QApplication was not created in the main() thread

I tried the command:

start_liveplotter(lambda: [odrv0.axis0.encoder.pos_estimate])

from within the interactive odrivetool instance as per the instructions here.

However, this throws the error:

Connected to ODrive 3653385F3030 as odrv0
In [1]: start_liveplotter(lambda: [odrv0.axis0.encoder.pos_estimate])
Out[1]: <fibre.utils.Event at 0x7fa37503e460>

/usr/local/lib/python3.8/dist-packages/odrive/utils.py:176: UserWarning: Starting a Matplotlib GUI outside of the main thread will likely fail.
  fig = plt.figure()
In [2]: WARNING: QApplication was not created in the main() thread.
Exception in thread Thread-3:
Traceback (most recent call last):
  File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.8/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "/usr/local/lib/python3.8/dist-packages/odrive/utils.py", line 184, in plot_data
    fig.canvas.start_event_loop(1/plot_rate)
  File "/usr/local/lib/python3.8/dist-packages/matplotlib/backends/backend_qt.py", line 408, in start_event_loop
    with _maybe_allow_interrupt(event_loop):
  File "/usr/lib/python3.8/contextlib.py", line 113, in __enter__
    return next(self.gen)
  File "/usr/local/lib/python3.8/dist-packages/matplotlib/backends/qt_compat.py", line 226, in _maybe_allow_interrupt
    old_wakeup_fd = signal.set_wakeup_fd(wsock.fileno())
ValueError: set_wakeup_fd only works in main thread

This seems to suggest that it is a matplotlib error that occurs when its functions are called from outside the main thread. Am I using this command incorrectly? Would really appreciate if someone could explain why I get this error since from the documentation it seems like this should just run?

I am using ODrive v3.6 - 56V; Firmware version: 0.5.4

Thank you.

Yeah, that’s normal. It should still open the plotter, and then throw weird errors when you close it.

Hi @Wetmelon, Thank you for your response.

When I attempt it, it does open the plotter window but its just a blank black window and I don’t see any live plot in it. On force quitting this window it kills the odrivetool interface along with the window. My Python version is 3.8. I am unsure if that is a factor.

1 Like

I had the same issue with the black plotter window. For me, the problem was that the graphics backend for matplotlib was QtAgg instead of KtAgg. See here for how to change that. Note that some of the methods they describe only apply to the current python instance and not every time python (or odrivetool) is launched. The matplotlibrc approach worked great for me as a permanent fix.

2 Likes

Hello

I have the same error. I m using odrive v3.6 56V fw v0.5.4 also. I am using python 3.10.12 via anaconda3 environment. Odrivetool works just fine. However, whenever I try to run odrivetool liveplotter, a window pops up and I get ValueError: set_wakeup_fd only works in main thread of the main interpreter. Odrivetool also becomes unusable. I have to open a new terminal and login again. @Matt I went through the solution you posted but I couldn’t quite understand. Isn’t there an easier solution to this situation?

I’m running into the same issue (different errors thrown) on Ubuntu 22.04 / Python 3.10.12, and switching the matplotlib graphics backend isn’t helping. But I’ve figured out that the odrive.utils.BulkCapture class can do what I need (tuning my gains). Start odrivetool and then use the following code:

capture = BulkCapture(lambda :[odrv0.axis0.encoder.pos_estimate, odrv0.axis0.controller.pos_setpoint], duration=0.4)
odrv0.axis0.controller.input_pos = 0.7 # Do stuff while capturing (like sending position commands)
capture.event.wait() # When you're done doing stuff, wait for the capture to be completed.
print(capture.data) # Do stuff with the data
capture.plot() # Plot the data

This captures asynchronously, and plots after the fact, on the main thread. Change duration as needed.

overshoot