Closed dogoepp closed 8 years ago
hi @dogoepp, we also have had the issue of multiple sensors and the order they are connected being a problem. The way we overcame this was instead of using port in the form of '/dev/ttyACM0' we used the value '/dev/serial/by-path/UNIQUE_IDENTIFIER' or '/dev/serial/by-id/UNIQUE_IDENTIFIER' as these values (symlinks to /dev/ACM0 path) are unique for each sensor. Have you considered this solution?
I don't have any /dev/serial folder on our computer. We (still) use Ubuntu 14.04 and the USB based 1 sensor DAQs.
hmm, that is strange. We are also using Ubuntu and 14.04 and USB based 1 sensor DAQs. The directory only exists if you have a serial device connected to your machine. If you can please confirm that you have checked for /dev/serial when a serial device is connected then I will take a look at your PR. Thanks!
What do you call a serial device ? I have the six sensors connected when I check the existence of this /dev/serial
folder. I didn't find it anyway.
May it be because the serial interface is emulated through a modem connexion (ttyACM) ?
would you be able to provide your dmesg logs of when you attach a sensor, as well as the output of lsusb and run: ll /lib/udev/rules.d/??-persistent-serial.rules And provide me with this output also. Thanks
The output of ldusb is
Bus 002 Device 002: ID 8087:8002 Intel Corp.
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 002: ID 8087:800a Intel Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 004 Device 005: ID 0451:8041 Texas Instruments, Inc.
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 121: ID 413c:2105 Dell Computer Corp. Model L100 Keyboard
Bus 003 Device 120: ID 046d:c077 Logitech, Inc. M105 Optical Mouse
Bus 003 Device 119: ID 0451:8043 Texas Instruments, Inc.
Bus 003 Device 040: ID 04d8:000a Microchip Technology, Inc. CDC RS-232 Emulation Demo
Bus 003 Device 039: ID 04d8:000a Microchip Technology, Inc. CDC RS-232 Emulation Demo
Bus 003 Device 038: ID 04d8:000a Microchip Technology, Inc. CDC RS-232 Emulation Demo
Bus 003 Device 037: ID 0424:2514 Standard Microsystems Corp. USB 2.0 Hub
Bus 003 Device 036: ID 0409:005a NEC Corp. HighSpeed Hub
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Where the Microchip Technology, Inc. CDC RS-232 Emulation Demo
are the three connected sensors.
The output of dmesg
is too long. I attach it as a file: dmesg.txt
Brilliant, thank you for that, could I also get the output of: ll /lib/udev/rules.d/??-persistent-serial.rules
it is this udev rule that creates the serial directory when the device is connected.
The path on our computer is resolved to /lib/udev/rules.d/60-persistent-serial.rules
and its content is
# do not edit this file, it will be overwritten on update
ACTION=="remove", GOTO="persistent_serial_end"
SUBSYSTEM!="tty", GOTO="persistent_serial_end"
KERNEL!="ttyUSB[0-9]*|ttyACM[0-9]*", GOTO="persistent_serial_end"
SUBSYSTEMS=="usb-serial", ENV{.ID_PORT}="$attr{port_number}"
IMPORT{builtin}="path_id"
ENV{ID_PATH}=="?*", ENV{.ID_PORT}=="", SYMLINK+="serial/by-path/$env{ID_PATH}"
ENV{ID_PATH}=="?*", ENV{.ID_PORT}=="?*", SYMLINK+="serial/by-path/$env{ID_PATH}-port$env{.ID_PORT}"
IMPORT{builtin}="usb_id"
ENV{ID_SERIAL}=="", GOTO="persistent_serial_end"
SUBSYSTEMS=="usb", ENV{ID_USB_INTERFACE_NUM}="$attr{bInterfaceNumber}"
ENV{ID_USB_INTERFACE_NUM}=="", GOTO="persistent_serial_end"
ENV{.ID_PORT}=="", SYMLINK+="serial/by-id/$env{ID_BUS}-$env{ID_SERIAL}-if$env{ID_USB_INTERFACE_NUM}"
ENV{.ID_PORT}=="?*", SYMLINK+="serial/by-id/$env{ID_BUS}-$env{ID_SERIAL}-if$env{ID_USB_INTERFACE_NUM}-port$env{.ID_PORT}"
LABEL="persistent_serial_end"
That is the same as on both my machine and my colleague's. Could you unplug the device, run: udevadm monitor --udev then reconnect the device and paste the output here. Also check for /dev/serial. If no /dev/serial, try a restart of your machine and again run the command during a reconnect of the device. Thanks
The output of udevadm monitor --udev
when connecting a hub with three sensors is
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
UDEV [57592.314829] add /devices/pci0000:00/0000:00:14.0/usb3/3-1 (usb)
UDEV [57592.316146] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1:1.0 (usb)
UDEV [57592.706425] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4 (usb)
UDEV [57592.707579] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4/3-1.4:1.0 (usb)
UDEV [57593.099324] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4/3-1.4.1 (usb)
UDEV [57593.100986] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4/3-1.4.1/3-1.4.1:1.0 (usb)
UDEV [57593.101664] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4/3-1.4.1/3-1.4.1:1.1 (usb)
UDEV [57593.102626] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4/3-1.4.1/3-1.4.1:1.0/tty/ttyACM0 (tty)
UDEV [57593.303327] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4/3-1.4.2 (usb)
UDEV [57593.304554] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4/3-1.4.2/3-1.4.2:1.1 (usb)
UDEV [57593.304585] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4/3-1.4.2/3-1.4.2:1.0 (usb)
UDEV [57593.305736] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4/3-1.4.2/3-1.4.2:1.0/tty/ttyACM1 (tty)
UDEV [57593.507605] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4/3-1.4.3 (usb)
UDEV [57593.508791] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4/3-1.4.3/3-1.4.3:1.0 (usb)
UDEV [57593.508970] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4/3-1.4.3/3-1.4.3:1.1 (usb)
UDEV [57593.509995] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4/3-1.4.3/3-1.4.3:1.0/tty/ttyACM2 (tty)
UDEV [57593.672058] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4/3-1.4.4 (usb)
UDEV [57593.673950] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4/3-1.4.4/3-1.4.4:1.1 (usb)
UDEV [57593.673981] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4/3-1.4.4/3-1.4.4:1.0 (usb)
UDEV [57593.675348] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4/3-1.4.4/3-1.4.4:1.0/tty/ttyACM3 (tty)
But, my bad, we had an udev rule that seemed to override the creation of the serial folder. Nonetheless, only one item is created for the optoforce sensor in /dev/serial/by-id
:
lrwxrwxrwx 1 root root 13 Aug 10 08:03 usb-OptoForce_OptoForce_DAQ-if00 -> ../../ttyACM2
lrwxrwxrwx 1 root root 13 Aug 10 08:03 usb-Xevelabs_USB2AX_74035303530351417142-if00 -> ../../ttyACM3
the usb-Xevelabs is an USB to dynamixel interface plugged on the same hub as the sensors.
After reboot, the output of udevadm
became
UDEV [52.154572] add /devices/pci0000:00/0000:00:14.0/usb3/3-1 (usb)
UDEV [52.155291] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1:1.0 (usb)
UDEV [52.550070] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4 (usb)
UDEV [52.550777] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4/3-1.4:1.0 (usb)
UDEV [52.939922] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4/3-1.4.1 (usb)
UDEV [52.941328] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4/3-1.4.1/3-1.4.1:1.1 (usb)
UDEV [52.943028] add /module/cdc_acm (module)
UDEV [52.944952] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4/3-1.4.1/3-1.4.1:1.0 (usb)
UDEV [52.944964] add /bus/usb/drivers/cdc_acm (drivers)
UDEV [52.945604] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4/3-1.4.1/3-1.4.1:1.0/tty/ttyACM0 (tty)
UDEV [53.129300] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4/3-1.4.2 (usb)
UDEV [53.129871] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4/3-1.4.2/3-1.4.2:1.0 (usb)
UDEV [53.129983] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4/3-1.4.2/3-1.4.2:1.1 (usb)
UDEV [53.130559] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4/3-1.4.2/3-1.4.2:1.0/tty/ttyACM1 (tty)
UDEV [53.348818] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4/3-1.4.3 (usb)
UDEV [53.349491] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4/3-1.4.3/3-1.4.3:1.0 (usb)
UDEV [53.349524] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4/3-1.4.3/3-1.4.3:1.1 (usb)
UDEV [53.350375] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4/3-1.4.3/3-1.4.3:1.0/tty/ttyACM2 (tty)
UDEV [53.530412] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4/3-1.4.4 (usb)
UDEV [53.531492] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4/3-1.4.4/3-1.4.4:1.1 (usb)
UDEV [53.531507] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4/3-1.4.4/3-1.4.4:1.0 (usb)
UDEV [53.532274] add /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.4/3-1.4.4/3-1.4.4:1.0/tty/ttyACM3 (tty)
but the content of /dev/serial/by-id
is still the same. Only one instance for the optoforce sensor where I would need three. We had tried to discriminate the sensors with udev but the (USB-provided) serial numbers are all the same. I guess it can't do better than use the USB-provided data.
Do you have the directory /dev/serial/by-path? It was the symlinks in this directory which we used as we also only had one instance in by-id
Also, briefly looking at your PR, I am unsure as to how this helps with the issue with having to plug the DAQs in the correct order as you are still assigning a port in the form /dev/ttyACMx Are you using all single channel DAQs? We have been using 1 multi and one single channel, so we need to know port corresponds to each. A snippet from one of our launch files:
`
The idea here is to get the serial number from the sensor by sending it a request. This part of the protocol is not in the official documentation but Optoforce was kind enough to tell me what to send and to receive. Then, we publish the wrench messages on a topic which is named with the serial number. For instance, on the single channel, single axis sensor ISE174, the topic published would be /optoforce_ISE174_0
(for starting_index = 0).
We connect to any optoforce serial interface available thanks to a udev rule that differentiates optoforce from any other ttyACM, but can't uniquely identify them. It is then the node's role to tell which sensor it is connected to.
I'm not very happy with this approach and better ideas are welcome.
----- Mail original -----
De: "kirstyellis" notifications@github.com À: "shadow-robot/optoforce" optoforce@noreply.github.com Cc: "Dorian Goepp" dorian.goepp@inria.fr, "Mention" mention@noreply.github.com Envoyé: Mercredi 10 Août 2016 12:50:35 Objet: Re: [shadow-robot/optoforce] Serial number (#20)
Also, briefly looking at your PR, I am unsure as to how this helps with the issue with having to plug the DAQs in the correct order as you are still assigning a port in the form /dev/ttyACMx Are you using all single channel DAQs? We have been using 1 multi and one single channel, so we need to know port corresponds to each. A snippet from one of our launch files: <
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub , or mute the thread .
Do you have the directory /dev/serial/by-path? It was the symlinks in this directory which we used as we also only had one instance in by-id
I'm afraid that the behavior is undetermined in this case. If I remember correctly, the path changes depending on which device is connected first and if they are disconnected and connected again.
----- Mail original -----
De: "kirstyellis" notifications@github.com À: "shadow-robot/optoforce" optoforce@noreply.github.com Cc: "Dorian Goepp" dorian.goepp@inria.fr, "Mention" mention@noreply.github.com Envoyé: Mercredi 10 Août 2016 12:05:21 Objet: Re: [shadow-robot/optoforce] Serial number (#20)
Do you have the directory /dev/serial/by-path? It was the symlinks in this directory which we used as we also only had one instance in by-id
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub , or mute the thread .
Would you be able to provide more details about the udev rule that you are referring to.
I am still not clear on how your method would work in the scenario that we have here, in our launch file where we are launching 2 instances of optoforce.launch, 1 single axis and one multi, what port names should we put in the launch file? As you say, these change based on the order of which is plugged in first so if I launch port /dev/ttyACM0 as a multichannel DAQ then unplug and it is now /dev/ttyACM1, what will happen?
We have been using the by-path, it isn't as solid as by-id as you mentioned but we found that it wasn't affected by the order that the devices were plugged in and so far the values assigned to the ports haven't changed apart from one occasion. It isn't ideal!
We set two rules in /etc/udev/rules.d/
:
optoforce.rules
:KERNEL=="ttyACM[0-9]", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="000a", SYMLINK="optoforce%n", MODE="660"
usb2ax.rules
:KERNEL=="ttyACM[0-9]", ATTRS{idVendor}=="16d0", ATTRS{idProduct}=="06a7", SYMLINK="usb2ax%n", MODE="660"
You have quite a point. Since I still have to tell the nodes which port to use, my approach is clearly not generic enough. It wouldn't handle your use case correctly. I my case, I have six sensors of the same type, which made it less of an issue (but I realise now that I had ignored that the scaling factors are specific to each sensor).
I could consider having each node scan through the ttyACM recognized to be DAQs and stick with the one having the right serial number. Only, having several programs (or nodes) attempting to access the same files almost at the same time might cause headackes.
Maybe an other approach could be to have a "detector" node that probes each connected DAQ for the serial number and the publishes on a topic the map between the serial number and software path. In this case, the optoforce nodes would wait for the "detector" node to publish information on the serial number they are looking for.
I unconsciously excluded the idea of having a single node that does the detection and publishing all alone. In that case, the scaling and sensor configuration might be configured through rosparam.
I'm considering to write a second program mapping the ports with the serial numbers.
After a short investigation, I could find two options:
a ROS node that searches for DAQs and provides a map from serial number to device full path (as a service or a topic)
is portable but might not be flexible on the timing of connection of the sensors and/or their disconnection
a script run by udev that names the device according to its serial number
is probably more robust but requires udev (no Mac OS compatibility)
What way would you think to be more approriate ?
cc: @jbmouret
@dogoepp, I think option 2 sounds like the best way to go, we are not concerned with Mac compatibility. Would you be able to provide a few more details about the work flow of this option. Ideally we would like the udev method to be optional so that if the udev rule is not installed, the user can provide a port name as before.
The udev approach allows to keep the ROS node simple. We only need to give it the path to the sensor, as it was done until now. The udev rule would ensure that we can use a reliable path, containing the serial number. I still have to check that it can work well.
Maybe an example can better illustrate the idea:
ISE177
/dev/optoforceISE177
optoforce
node to the value above and we are sure that it will always be the same sensor we talk to. In that case, we don't need to have the sensor's serial number in the topic's name.In this case, the current master version of the node would work. However, I need to talk to the sensors to get its serial number. I would like to use the node's communication code to do so. So, if it's fine for you, I would make OptoforceDriver ROS-agnostic, adapt the node and create a second program that only gets the serial number, using this Optoforce class.
sounds great!
Since a lot of work was done and I could not keep working on the serial_number branch as others used it, I had to create the new pull request #23. I close this one.
Since we have six sensors on one robot, we need to have a way to uniquely identify them. Using the name that the OS gives them is not reliable enough since it depends on the order in which they are connected.
I propose to add the option for the topic name to contain the sensor's serial number.
A number of other changes were made, hopefully for the better.
Changes:
~append_serial_number
to the node enabling the serial number based topic name (default to previous behaviour)_frame_header
that was not generic and used only once