johnhw / pyspacenavigator

3Dconnexion Space Navigator in Python using raw HID (windows only)
MIT License
64 stars 26 forks source link

button_callback changed in 0.2.1, receives [0, 0] on button down #7

Closed speleo3 closed 5 years ago

speleo3 commented 5 years ago

Up to version 0.2, the two buttons on my SpaceNavigator were sending [1, 0] (left) and [0, 1] (right) on button down.

# git checkout 0.2
# python spacenavigator.py
Devices found:
        SpaceNavigator
SpaceNavigator found
SpaceNavigator connected to 3Dconnexion Space Navigator version: 1056 [serial: ]
   x +0.00    y +0.00    z +0.00 roll +0.00 pitch +0.00  yaw +0.00    t -1.00
buttons=[1, 0]  <-- left button down
   x +0.00    y +0.00    z +0.00 roll +0.00 pitch +0.00  yaw +0.00    t -1.00
buttons=[0, 0]
   x +0.00    y +0.00    z +0.00 roll +0.00 pitch +0.00  yaw +0.00    t -1.00
buttons=[0, 1]  <-- right button down
   x +0.00    y +0.00    z +0.00 roll +0.00 pitch +0.00  yaw +0.00    t -1.00
buttons=[0, 0]

Since version 0.2.1, the left button sends [0, 1], and the right buttons sens [0, 0] on button down.

# git checkout 0.2.1
# python spacenavigator.py
Devices found:
        SpaceNavigator
SpaceNavigator found
9
1
1
1
1
1
1
SpaceNavigator connected to 3Dconnexion Space Navigator version: 1056 [serial: ]
   x +0.00    y +0.00    z +0.00 roll +0.00 pitch +0.00  yaw +0.00    t -1.00
   x +0.50    y +0.48    z +0.50 roll +0.49 pitch +0.50  yaw +0.50    t +1.51
buttons=[0, 1]  <-- left button down
buttons=[0, 0]
buttons=[0, 0]  <-- right button down
buttons=[0, 0]

In addition to that, if the button is pressed before any axis is touched, I get an exception:

# git checkout 0.2.1
# python spacenavigator.py
Devices found:
        SpaceNavigator
SpaceNavigator found
9
1
1
1
1
1
1
SpaceNavigator connected to 3Dconnexion Space Navigator version: 1056 [serial: ]
buttons=[]
Exception in thread Thread-1:
Traceback (most recent call last):
  File "spacenavigator.py", line 118, in <lambda>
    button_handler = lambda value, id, button_id=usage : self.button_handler(button_id, value)
  File "spacenavigator.py", line 151, in button_handler
    self.button_callback(self.tuple_state, self.tuple_state.buttons)
  File "spacenavigator.py", line 412, in toggle_led
    if buttons[0] == 1:
IndexError: list index out of range
johnhw commented 5 years ago

Thanks for fixing these! Both PRs merged now.

speleo3 commented 5 years ago

Thanks for merging!

PR #9 didn't fix this issue, sorry if I caused any confusion. It only allows int() conversion of the list-bitmask, but I haven't figured out yet why it sends [0, 0] on button down. Please reopen #7.

speleo3 commented 5 years ago

Gathering some data:

Observed with the following code in analyse_usages():

            if usage_page==BUTTON_PAGE:                        
                import pprint
                pprint.pprint(all_items)        
                for usage in range(all_items["usage_min"], all_items["usage_max"]+1):
                    full_usage_id = hid.get_full_usage_id(usage_page, usage)
                    self.device.add_event_handler(full_usage_id, print, hid.HID_EVT_CHANGED,  'CHANGED  usage={}'.format(usage))
                    self.device.add_event_handler(full_usage_id, print, hid.HID_EVT_PRESSED,  'PRESSED  usage={}'.format(usage))
                    self.device.add_event_handler(full_usage_id, print, hid.HID_EVT_RELEASED, 'RELEASED usage={}'.format(usage))
                    self.device.add_event_handler(full_usage_id, print, hid.HID_EVT_SET,      'SET      usage={}'.format(usage))
                    self.device.add_event_handler(full_usage_id, print, hid.HID_EVT_CLEAR,    'CLEAR    usage={}'.format(usage))

Output:

python spacenavigator.py
Devices found:
        SpaceNavigator
SpaceNavigator found
{'bit_field': 2,
 'data_index_max': 7,
 'data_index_min': 6,
 'designator_max': 0,
 'designator_min': 0,
 'is_absolute': 1,
 'is_alias': 0,
 'is_button': True,
 'is_designator_range': 0,
 'is_range': 1,
 'is_string_range': 0,
 'is_value': False,
 'link_collection': 3,
 'link_usage': 0,
 'link_usage_page': 1,
 'report_id': 3,
 'string_max': 0,
 'string_min': 0,
 'usage_max': 2,
 'usage_min': 1,
 'usage_page': 9}
SpaceNavigator connected to 3Dconnexion Space Navigator version: 1056 [serial: ]
   x +0.00    y +0.00    z +0.00 roll +0.00 pitch +0.00  yaw +0.00    t -1.00
   x +0.02    y -0.02    z +0.00 roll +0.00 pitch -0.01  yaw +0.00    t +7.91
1 2 CHANGED  usage=1  <-- button 1 pressed
1 3 PRESSED  usage=1
1 5 SET      usage=1
0 2 CHANGED  usage=1  <-- button 1 released
0 4 RELEASED usage=1
0 6 CLEAR    usage=1
0 6 CLEAR    usage=1  <-- button 2 pressed
0 6 CLEAR    usage=1  <-- button 2 released
johnhw commented 5 years ago

This is really messy :( It looks like the event handler just doesn't work right for the last button in Windows -- this seems to be a known problem, though I've mislaid the reference.

The raw stream works fine. I could attach both a raw stream handler (to just handle the buttons) and the specific usage page event handler for the remainder of the controls, but pywinusb disables all other event handlers if a raw stream handler is enabled...

The upshot is that there isn't a clean way I can find to make the automatic extraction of the usage info for the buttons, LED and axis work. I've reverted to the fixed assignments based on the DeviceSpec info in this branch.

speleo3 commented 5 years ago

Thanks for the fix! I can confirm that version 0.2.2 behaves as expected again.