Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

'RelativeAxis' object has no attribute 'max' error when using tablet. #491

Closed
gdburton opened this issue Oct 19, 2021 · 5 comments
Closed
Labels
crash Bugs which cause pyglet/python to crash linux Linux Specific

Comments

@gdburton
Copy link

gdburton commented Oct 19, 2021

(Excuse a newbie here!)
I am hitting a problem using a Wacom tablet running https://github.com/pyglet/pyglet/blob/master/examples/input/tablet.py on Linux Mint (and Rasp Pi)
Error log looks like this:-
Tablets: (1) XInput Tablet Press number key to open corresponding tablet device. Traceback (most recent call last): File "/home/glenn/projects/python/wacom/tablet-ex.py", line 60, in <module> pyglet.app.run() File "/usr/local/lib/python3.8/dist-packages/pyglet/app/__init__.py", line 107, in run event_loop.run() File "/usr/local/lib/python3.8/dist-packages/pyglet/app/base.py", line 168, in run platform_event_loop.step(timeout) File "/usr/local/lib/python3.8/dist-packages/pyglet/app/xlib.py", line 121, in step device.select() File "/usr/local/lib/python3.8/dist-packages/pyglet/canvas/xlib.py", line 205, in select dispatch(e) File "/usr/local/lib/python3.8/dist-packages/pyglet/window/xlib/__init__.py", line 979, in dispatch_platform_event_view event_handler(e) File "/usr/local/lib/python3.8/dist-packages/pyglet/window/xlib/__init__.py", line 1152, in _event_key_view self.dispatch_event('on_text', text) File "/usr/local/lib/python3.8/dist-packages/pyglet/window/__init__.py", line 1333, in dispatch_event if EventDispatcher.dispatch_event(self, *args) != False: File "/usr/local/lib/python3.8/dist-packages/pyglet/event.py", line 408, in dispatch_event if handler(*args): File "/home/glenn/projects/python/wacom/tablet-ex.py", line 31, in on_text canvas = tablets[i].open(window) File "/usr/local/lib/python3.8/dist-packages/pyglet/input/x11_xinput_tablet.py", line 56, in open return XInputTabletCanvas(window, self.cursors) File "/usr/local/lib/python3.8/dist-packages/pyglet/input/x11_xinput_tablet.py", line 74, in __init__ cursor.max_pressure = device.axes[2].max AttributeError: 'RelativeAxis' object has no attribute 'max'

The tablet is definitely working in Absolute mode so I am confused by the error.
I had a program based closely on this example working a few months back. I am unsure what has been updated since.
I have tested with Pyglet 1.5.16 and 2.0.dev9 with the same error.

Any assistance is appreciated.

@benmoran56
Copy link
Member

The tablet code on Linux was changed a while back to include more "cursor" types. Tablets are made up of a few distinct devices on Linux (the "cursors"), and some of them were being missed for some devices.

The XInputTabletCanvas code still expects all Cursors to be AbsoluteAxis, so it looks like a RelativeAxis one has slipped in.
The current code for querying Tablets looks like this:

def get_tablets(display=None):
    # Each cursor appears as a separate xinput device; find devices that look
    # like Wacom tablet cursors and amalgamate them into a single tablet. 
    valid_names = ('stylus', 'cursor', 'eraser', 'wacom', 'pen', 'pad')
    cursors = []
    devices = get_devices(display)
    for device in devices:
        dev_name = device.name.lower().split()
        if any(n in dev_name for n in valid_names) and len(device.axes) >= 3:
            cursors.append(XInputTabletCursor(device))
    if cursors:
        return [XInputTablet(cursors)]
    return []

The logic is basically:

  • Query all devices with pyglet.input.get_devices()
  • Check if a device.name is in the valid list, AND has at least 3 axis. If so, create a XInputTabletCursor.
  • If at least one Cursor exists, create and return an XinputTablet instance.

I don't currently have access to a Tablet myself, so I'm unable to check this on my side.
If you can do a little troubleshooting on your end, perhaps we can figure out a way to exclude the bogus devices.
As a first step, perhaps you can create a tablet instance manually, from only specific cursors.

@benmoran56 benmoran56 added crash Bugs which cause pyglet/python to crash linux Linux Specific labels Oct 20, 2021
@gdburton
Copy link
Author

gdburton commented Oct 20, 2021

Many thanks for the fast response.
I made some simple edits to the x11_xinput_tablet.py file. Initially putting a print in line 122 to show the device names found.
Line 116 was originally valid_names =('stylus', 'cursor', 'eraser', 'wacom', 'pen', 'pad')

It found:-
['wacom', 'bamboo', '16fg', '4x5', 'pen', 'stylus']
['wacom', 'bamboo', '16fg', '4x5', 'finger', 'touch']
['wacom', 'bamboo', '16fg', '4x5', 'pad', 'pad']
['wacom', 'bamboo', '16fg', '4x5', 'pen', 'eraser']

Then I removed 'wacom' from Line 116.
This worked with these devices found.
['wacom', 'bamboo', '16fg', '4x5', 'pen', 'stylus']
['wacom', 'bamboo', '16fg', '4x5', 'pad', 'pad']
['wacom', 'bamboo', '16fg', '4x5', 'pen', 'eraser']
So the "'finger', 'touch'" dev has been lost, which indicates the one causing the RelativeAxis error.
Obviously, I can't say that that is "the fix" that should be implemented as I don't know what device "wacom" was intended to catch.
But at least for my relatively low-end, Wacom CTH-470, device, this sorts the RelativeAxis problem.

While I have your attention I have also tripped over an error in the examples/input/tablet.py file.
Lines 46 & 47

def on_motion(cursor, x, y, pressure):

        print('%s: on_motion(%r, %r, %r, %r)' % (name, cursor, x, y, pressure))

But the on_motion event responds with 6 parameters, not 4 so these lines could be replaced with.

def on_motion(cursor, x, y, pressure, a, b):

        print('%s: on_motion(%r, %r, %r, %r, %r, %r)' %(name, cursor, x, y, pressure, a, b))

I think the extra ones (a&b) are related to pen tilt, but my tablet does not provide these so responds with zero for each.

Anyway, I hope that this will help the project. I am still in the early stages of using pyglet for a test program to help characterise and calibrate a small robot arm. The arm will hold the tablet pen and I will use the landing positions to ensure the control system is meeting the specifications.

All the best

@benmoran56
Copy link
Member

Thanks for looking into this.

I think you found the culprit, with the the wacom name.
Looking at the Git history, the previous whitelist was just ('stylus', 'cursor', 'eraser'), so we added "'wacom", "pen", and "pad". The "pen" and "pad" should still be fine, but it looks like "wacom" is going to double-match some things, including things we don't want. In the short term, it should be fine to just remove the "wacom" name, since the type of device should also always be included in the name.

As for the on_motion event, good catch. The Table base class in input/base.py has the docstrings, but is also missing the parameters. I'll make a few quick fixes to the 1.5-maintenance branch. After that, if you could confirm operation on your side, I can get these fixes into the next point release.

@benmoran56
Copy link
Member

Please give it a try with the 1.5-maintenance branch. If you're installing via pip, you can use:

pip install --user git+https://github.com/pyglet/pyglet.git@pyglet-1.5-maintenance

@gdburton
Copy link
Author

@benmoran56 Many thanks for your efforts.

All is working fine after this update.
Happy to close this issue.

All the best

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
crash Bugs which cause pyglet/python to crash linux Linux Specific
Projects
None yet
Development

No branches or pull requests

2 participants