joystick_drivers icon indicating copy to clipboard operation
joystick_drivers copied to clipboard

device_name param ignored ROS2

Open Achllle opened this issue 5 years ago • 1 comments

I'm using an xbox360 located at /dev/input/js0 / /dev/input/event0 on my machine on ROS2 Foxy. I specified these parameters as

            parameters=[
                {"device_name": "'/dev/input/js0"},
                {"device_id": 2}
            ],

I noticed that when device_id is set incorrectly but device_name is correct, the joystick isn't found. Vice versa when device_name is set incorrectly but device_id is set correctly` the joystick is found.

The documentation states

The joystick name to use. This can be useful when multiple different joysticks are attached. If both device_name and device_id are specified, device_name takes precedence.

Achllle avatar Feb 15 '21 22:02 Achllle

I was having problems with Joy also and came across your issue. I think I discovered the bug in the handleJoyDeviceAdded function.

Here's the code snippet for reference:

void Joy::handleJoyDeviceAdded(const SDL_Event & e)
{
  if (!dev_name_.empty()) {
    int num_joysticks = SDL_NumJoysticks();
    if (num_joysticks < 0) {
      RCLCPP_WARN(get_logger(), "Failed to get the number of joysticks: %s", SDL_GetError());
      return;
    }
    for (int i = 0; i < num_joysticks; ++i) {
      const char * name = SDL_JoystickNameForIndex(i);
      if (name == nullptr) {
        RCLCPP_WARN(get_logger(), "Could not get joystick name: %s", SDL_GetError());
        continue;
      }
      if (std::string(name) == dev_name_) {
        // We found it!
        dev_id_ = i;
        break;
      }
    }
  }

  if (e.jdevice.which != dev_id_) {
    return;
  }

  ...

Say you set device_name to /some/fake/device and you set device_id to 0 (and there is a valid 0 device on your machine). When the joy_node is created, it will set dev_name_ to be /some/fake/device and dev_id_ to be 0.

Now comes this function. This function (I assume) is called whenever a new device is added (like at the beginning of the node running). It checks if dev_name_ is empty: it is not. Then it iterates over all of the joysticks (let's assume a few are connected). None of the joysticks match dev_name_ so we never update dev_id_ (the if (std::string(name) == dev_name_) { line). This means dev_id_ is still 0! So if (e.jdevice.which != dev_id_) { will presumably pass because dev_id_ is a valid device ID.

This function needs a way to return early if the dev_name_ is never found.

Specs: Pop!_OS 20.04, ROS Foxy

tigressine avatar Apr 24 '21 23:04 tigressine