How to use two USB devices in /dev that have identical profiles

1,256 views
Skip to first unread message

Michael Wimble

unread,
Oct 3, 2022, 8:22:29 PM10/3/22
to hbrob...@googlegroups.com
I now have two LIDARs in Puck, instead of one, and they are both identical pieces of hardware. When I plug them in, they get mounted as /dev/ttyUSB0 and /dev/ttyUSB1. But, as is usual for Linux, it is not stable as to which LIDAR gets mapped to which dev entry. And, if you unplug and replug either LIDAR, it gets assigned a different device name. This makes it impossible to write a script that correctly references a specific LIDAR using the /dev name entry.

The following assumes you know how the Linux “udev” system works, so I won’t expound on how to create the udev files and restart the udev system.

My trick is to plug the two LIDARs into different USB controllers on my motherboard, ensuring they get assigned to two different USB busses. Note that this solution won’t work for computers that have only a single USB controller. Now I can used the “udev” system in Linux to fix the issue.


Here is what lsusb shows for the two LD06 LIDARs after plugging them in:

lsusb
Bus 003 Device 002: ID 10c4:ea60 Silicon Labs CP210x UART Bridge
Bus 001 Device 009: ID 10c4:ea60 Silicon Labs CP210x UART Bridge

So one device is plugged into the USB bus 3, and the other into the USB bus 1.

Here are two different ways to write a udev rule to deal with this:

more /etc/udev/rules.d/02-ldrobot.rules
KERNEL=="ttyUSB*", ATTRS{busnum}=="3", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", MODE:="0777”, SYMLINK+="lidar_left_front"

ATTRS{busnum}=="1", ATTRS{idVendor}=="10c4", MODE:="0777" SYMLINK+="lidar_right_rear"

Your e-mail client may show the first line that starts with KERNEL as two lines, but it is one line in the file.

Note that both devices have the same idVendor and idProduct values. The first rule is a bit over specified, so you might be able to just use the second rule as a pattern. It reads:

If a new device is found and the bus number is 1, and the vendor ID is 10c4, set the mode of the device to octal 777 (i.e., anyone can use the device) and create a symbolic link named /dev/lidar_right_rear.

The first rule does the same in a slightly different way, relying on the second LIDAR being plugged into the USB bus 3, and assigning a symbolic name of /dev/lidar_left_front.

Now my launch files can refer to the symbolic name of the LIDAR and it works even when the LIDARs are power cycled (e.g., unplugged and plugged in again).

Off topic, in case you are wondering, I replaced my older LIDAR which came from a Neato vacuum cleaner, which makes 360 readings per revolution at a spin rate of 3 times per second, with a pair of newer LIDARs that scan 450 readings per revolution at a spin rate of 10 times per second. 

How fast your LIDAR spins directly affects how fast your robot can move and how much error you get in localization. This should be obvious because even in a tenth of a second the robot will have moved some distance between the start of a LIDAR revolution and the end of that revolution. So the distances reported by the LIDAR are in some sense false, as they are used by ROS in a way that it assumes that the distances are all from the center of the LIDAR spin at the reported instance of time.

So, faster LIDARs make the error smaller. And, I mounted the two LIDARs are different heights on Puck, so instead of a single, pencil-thin view of the world, I now have two, pencil-thin views at different heights.

Also, my single LIDAR was mounted atop the top plate of Puck, which is where I  need to mount the arm and gripper (eventually). The new LIDARs are mounted at two corners of the robot, between the top and bottom plates. Of course, now each LIDAR only gets a 270 degree view of the world, as the robot body gets in the way of 90 degrees of the spin. It took a few minutes of micro adjusting the URDF of the robot to get the two scans to reasonably overlap to show the same distance to the same object. Of course, it’s not exactly correct. At longer distances, the two LIDARs have different errors, so the points are not totally coincident. But it’s “good enough”. So it seems at the moment.

Chris Albertson

unread,
Oct 3, 2022, 8:35:09 PM10/3/22
to hbrob...@googlegroups.com
Do the two LiDARs have and overlapping field of view?  If there is some way the two can look at the same object then each wuld see the same point as having a different distance.   But I'd guess they might not be looking at the same place.

So, maybe each LIDAR is blocked by a different part of the robot's structure, and this blockage would be 100% predictable.

In short look at the data.   Then after you look at the data, then decide which topic to publish it on.

The exact same problem happens when you plug-in two gamepad controllers.  The only good otin is to display a notice on screen "operate any control on controller #1" and then wait for data.       I don't see any way out of this except to look at the data somehow. 

--
You received this message because you are subscribed to the Google Groups "HomeBrew Robotics Club" group.
To unsubscribe from this group and stop receiving emails from it, send an email to hbrobotics+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/hbrobotics/16E16868-C98D-4D2B-AB61-69B7008E0313%40gmail.com.


--

Chris Albertson
Redondo Beach, California

David Hough

unread,
Oct 3, 2022, 8:44:40 PM10/3/22
to hbrob...@googlegroups.com
Some devices have a serial number so you can tell them apart so that
even if you plug them in differently next time, you can still find which
is which. It'll be in the iSerial field if you do an "lsusb -v" with
root privilege.

This is an FTDI USB-serial adapter and I know they have serial numbers,
this one being FTALGLTJ

To narrow it down, find the bus and device with a plain lsusb and then
interrogate just that device with "lsusb -s bus:device -v"

Bus 003 Device 022: ID 0403:6001 Future Technology Devices
International, Ltd FT232 Serial (UART) IC
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 0
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0x0403 Future Technology Devices International, Ltd
idProduct 0x6001 FT232 Serial (UART) IC
bcdDevice 6.00
iManufacturer 1 FTDI
iProduct 2 TTL232R-3V3
iSerial 3 FTALGLTJ
bNumConfigurations 1

If you do have devices with unique serial numbers then I'm guessing
there's a way to pick that up with the udev rule.

Also, "udevadm info <device>" will give you the information including
the serial number, for this device it throws up this pair of lines

E: ID_SERIAL=FTDI_TTL232R-3V3_FTALGLTJ
E: ID_SERIAL_SHORT=FTALGLTJ


Dave

Michael Wimble

unread,
Oct 3, 2022, 8:52:03 PM10/3/22
to hbrob...@googlegroups.com
They do see the same objects in the overlapping fields. The ROS tf system handles this all with no coding needed by me. Each camera publishes to a different topic and I modified the ira_laser_tools module to work better with the Galactic ROS distribution so it merges the two laser beams to produce one, unified scan. I had hoped that slam_toolbox would take two different laser inputs, but I see conflicting statements as to whether that works and I haven’t had time to read the source code yet.

I don’t know of a way to look at the two scans, even with overlapping fields, and decide that one set of data must be from the front LIDAR vs the back LIDAR, unless I make an inference about where the robot is in my house and hope it is in some position in the house with asymmetric features.

My game controller comes in over bluetooth, when I decide to use it. I don’t know of a good way to deal with this using bluetooth other than what I did, namely buy controllers from different manufacturers so that they have different attributes. And I wrote my own bluetooth controller handler for ROS to make the buttons do what I want. But buying LIDARs from different manufacturers would be a bit of a problem, especially financially.

I wish manufacture’s would somehow include a dip switch or a way to write to the onboard eprom to give each device a different USB attribute of some sort that I could use with udev. The VL53L0X time-of-flight sensors over I2C allow this, and my previous use of the chips did this, though you have to provide an extra chip-select line to the chip and it has to be done each time the device powers up. But I could live with that (other than USB doesn’t give me a good way to provide a chip-select equivalent).

Now that I think of it, I think my LIDARs have UART outputs besides USB, but I don’t have a lot of UARTs on the computer I want the LIDARs to talk to.

Michael Wimble

unread,
Oct 3, 2022, 8:55:57 PM10/3/22
to hbrob...@googlegroups.com
The two LIDARs have identical USB information as they are the same part from the same manufacturer. It would be nice the manufactures of OEM equipment would deal with this better. And yes, if they had different serial numbers, I could write a udev rule to deal with it.

Marco Walther

unread,
Oct 3, 2022, 8:56:38 PM10/3/22
to hbrob...@googlegroups.com, Michael Wimble
On 10/3/22 17:22, Michael Wimble wrote:
> I now have two LIDARs in Puck, instead of one, and they are both
> identical pieces of hardware. When I plug them in, they get mounted as
> /dev/ttyUSB0 and /dev/ttyUSB1. But, as is usual for Linux, it is not
> stable as to which LIDAR gets mapped to which dev entry. And, if you
> unplug and replug either LIDAR, it gets assigned a different device
> name. This makes it impossible to write a script that correctly
> references a specific LIDAR using the /dev name entry.
>
> The following assumes you know how the Linux “udev” system works, so I
> won’t expound on how to create the udev files and restart the udev system.
>
> My trick is to plug the two LIDARs into different USB controllers on my
> motherboard, ensuring they get assigned to two different USB busses.
> Note that this solution won’t work for computers that have only a single
> USB controller. Now I can used the “udev” system in Linux to fix the issue.
>

You 'can' use a similar trick as long as you plug your devices into the
same plug all the time. The USB tree knows, which devices is connected
to which controller and all the way to the 'plug';-)

That's how my tree looks like for my laptop right now.

(base) marcow@feather6:~$ sudo lsusb -t
[sudo] password for marcow:
/: Bus 06.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/2p, 10000M
|__ Port 2: Dev 2, If 0, Class=Hub, Driver=hub/4p, 10000M
|__ Port 1: Dev 3, If 0, Class=Hub, Driver=hub/4p, 10000M
|__ Port 2: Dev 4, If 0, Class=Vendor Specific Class,
Driver=r8152, 5000M
/: Bus 05.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/2p, 480M
|__ Port 2: Dev 2, If 0, Class=Hub, Driver=hub/5p, 480M
|__ Port 1: Dev 3, If 0, Class=Hub, Driver=hub/4p, 480M
|__ Port 1: Dev 5, If 0, Class=Hub, Driver=hub/2p, 480M
|__ Port 2: Dev 6, If 0, Class=Audio,
Driver=snd-usb-audio, 12M
|__ Port 2: Dev 6, If 1, Class=Audio,
Driver=snd-usb-audio, 12M
|__ Port 2: Dev 6, If 2, Class=Audio,
Driver=snd-usb-audio, 12M
|__ Port 2: Dev 6, If 3, Class=Human Interface Device,
Driver=usbhid, 12M
|__ Port 3: Dev 4, If 2, Class=Audio, Driver=snd-usb-audio, 480M
|__ Port 3: Dev 4, If 0, Class=Video, Driver=uvcvideo, 480M
|__ Port 3: Dev 4, If 3, Class=Audio, Driver=snd-usb-audio, 480M
|__ Port 3: Dev 4, If 1, Class=Video, Driver=uvcvideo, 480M
|__ Port 5: Dev 7, If 0, Class=, Driver=, 480M
/: Bus 04.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/2p, 10000M
/: Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/2p, 480M
/: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/10p, 10000M
/: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/16p, 480M
|__ Port 2: Dev 2, If 2, Class=Chip/SmartCard, Driver=, 12M
|__ Port 2: Dev 2, If 0, Class=Human Interface Device,
Driver=usbhid, 12M
|__ Port 2: Dev 2, If 1, Class=Human Interface Device,
Driver=usbhid, 12M
|__ Port 8: Dev 3, If 3, Class=Video, Driver=uvcvideo, 480M
|__ Port 8: Dev 3, If 1, Class=Video, Driver=uvcvideo, 480M
|__ Port 8: Dev 3, If 2, Class=Video, Driver=uvcvideo, 480M
|__ Port 8: Dev 3, If 0, Class=Video, Driver=uvcvideo, 480M
|__ Port 9: Dev 4, If 0, Class=Vendor Specific Class, Driver=, 12M
|__ Port 10: Dev 5, If 0, Class=Human Interface Device,
Driver=usbhid, 12M
|__ Port 14: Dev 6, If 0, Class=Wireless, Driver=btusb, 12M
|__ Port 14: Dev 6, If 1, Class=Wireless, Driver=btusb, 12M


And after plugging in a hub with two identical USB-TTL serial
interfaces, I have

/: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/16p, 480M
|__ Port 2: Dev 2, If 2, Class=Chip/SmartCard, Driver=, 12M
|__ Port 2: Dev 2, If 0, Class=Human Interface Device,
Driver=usbhid, 12M
|__ Port 2: Dev 2, If 1, Class=Human Interface Device,
Driver=usbhid, 12M
|__ Port 6: Dev 7, If 0, Class=Hub, Driver=hub/4p, 480M
|__ Port 4: Dev 10, If 0, Class=Vendor Specific Class,
Driver=ftdi_sio, 12M
|__ Port 1: Dev 11, If 0, Class=Vendor Specific Class,
Driver=ftdi_sio, 12M

Bus 001 Device 010: ID 0403:6001 Future Technology Devices
International, Ltd FT232 Serial (UART) IC
Bus 001 Device 011: ID 0403:6001 Future Technology Devices
International, Ltd FT232 Serial (UART) IC


>
> Here is what lsusb shows for the two LD06 LIDARs after plugging them in:
>
> lsusb
> Bus 003 Device 002: ID 10c4:ea60 Silicon Labs CP210x UART Bridge
> Bus 001 Device 009: ID 10c4:ea60 Silicon Labs CP210x UART Bridge
>
> So one device is plugged into the USB bus 3, and the other into the USB
> bus 1.
>
> Here are two different ways to write a udev rule to deal with this:
>
> more /etc/udev/rules.d/02-ldrobot.rules
> KERNEL=="ttyUSB*", ATTRS{busnum}=="3", ATTRS{idVendor}=="10c4",
> ATTRS{idProduct}=="ea60", MODE:="0777”, SYMLINK+="lidar_left_front"
>
> ATTRS{busnum}=="1", ATTRS{idVendor}=="10c4", MODE:="0777"
> SYMLINK+="lidar_right_rear"
>

You would add an ATTRS{devpath}=="6.4" or ATTRS{devpath}=="6.1" for my
two little boards;-)

Something like
KERNEL=="ttyUSB*", ATTRS{busnum}=="1" ATTRS{devpath}=="6.4"
ATTRS{idVendor}=="0403" ATTRS{idProduct}=="6001" SYMLINK+="foo4"
KERNEL=="ttyUSB*", ATTRS{busnum}=="1" ATTRS{devpath}=="6.1"
ATTRS{idVendor}=="0403" ATTRS{idProduct}=="6001" SYMLINK+="foo1"

That depends on the same device always being plugged into the same port!

Setting the mode to 777 is usually a bad idea:-( First of, you don't
want to 'execute' those files and even 666 can usually be avoided in
favor of a better 660 with the accessing users in the correct groups;-)


man udevadm gives you a lot of info;-) For instance, something like

udevadm info -a -p $(udevadm info -q path -n /dev/ttyUSB0)

;-)

I hope, this helps a bit;-) udev is your friend when you need or want to
connect many USB (or other) devices;-)

-- Marco
> --
> You received this message because you are subscribed to the Google
> Groups "HomeBrew Robotics Club" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to hbrobotics+...@googlegroups.com
> <mailto:hbrobotics+...@googlegroups.com>.
> <https://groups.google.com/d/msgid/hbrobotics/16E16868-C98D-4D2B-AB61-69B7008E0313%40gmail.com?utm_medium=email&utm_source=footer>.

Chris Albertson

unread,
Oct 3, 2022, 9:08:02 PM10/3/22
to hbrob...@googlegroups.com
Cheap solution.   My LIDARs are dirt cheap units salvaged from vacuum cleaners and sold on eBay.  These are going for as little as $10 for a spinning LIDAR if you buy in China and abut $35 for US resellers   

Then I use a $3 "STM32, BluePill" for the LIDAR to computer interface.   This is mechanically and functionall identical to the LP LIDAR you can buy for $100 or so.    

If it were me it would be easy to modify the software to provide an ID fr the LIDAR.  With more effort I would use one STM32 to control both LIDARS and send the data one USB port.    

But my plan is to re-do this using a Raspberry Pi Pico.   I'm waiting until after my Robot needs Lidar, if it ever does.

--
You received this message because you are subscribed to the Google Groups "HomeBrew Robotics Club" group.
To unsubscribe from this group and stop receiving emails from it, send an email to hbrobotics+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/hbrobotics/fc0ed37b-5cfb-715b-4cc3-757ff0915f45%40uks.org.uk.

George Campbell

unread,
Oct 3, 2022, 10:23:48 PM10/3/22
to hbrob...@googlegroups.com
I’m surprised libraries don’t take the "rolling shutter” effect of spinning LIDAR into account when incorporating the readings.

Marco Walther

unread,
Oct 3, 2022, 10:34:54 PM10/3/22
to hbrob...@googlegroups.com, George Campbell
On 10/3/22 19:23, George Campbell wrote:
> I’m surprised libraries don’t take the "rolling shutter” effect of spinning LIDAR into account when incorporating the readings.

That would have to be the 'driver'. Once it's a message on a ROS topic,
nothing really knows, how the points were found.

James Nugen

unread,
Oct 4, 2022, 12:36:17 AM10/4/22
to hbrob...@googlegroups.com
Silicon Labs apparently has a utility to set the SN:
https://community.silabs.com/s/article/using-more-than-one-cp210x-device-simultaneously?language=en_US
> --
> You received this message because you are subscribed to the Google Groups "HomeBrew Robotics Club" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to hbrobotics+...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/hbrobotics/b2844b2f-fefd-aa84-e07b-6cdadd1d825e%40gmail.com.

Chris Albertson

unread,
Oct 4, 2022, 12:48:55 AM10/4/22
to hbrob...@googlegroups.com
A couple ideas..

(1) If there are two LIDAR units, then there MUST be some structure on the robot that blocks at least one LIDAR.  If nothing else, one LIDAR blocks the other.  Can you look for the fixed structure that blocks the LIDAR?  

(2) What if you rotated one LIDAR unit relative to the other so the "zero" degrees were not facing the same way.   Move one 90 degrees.    Now if you drive forward about 50 millimeters, one LIDAR will see everything move 50mm "forward" and the other will see eveythng move 50 mm "sideways".    Later use TF to "fix" the rotation.   The LIDARs don't need to see the same objects, you are only detecting gross movement of the whole point cloud.   In fact you could just take the average (x,y) of a few hundred raw LIDAR points before and after the move.




Michael Wimble

unread,
Oct 4, 2022, 12:54:14 AM10/4/22
to hbrob...@googlegroups.com
A good idea that could fix this specific problem. My paper, though was to address people that have the general problem of multiple, identical usb devices. Thanks for thinking about a creative solution, though. 

On Oct 3, 2022, at 9:48 PM, Chris Albertson <alberts...@gmail.com> wrote:



Dave Everett

unread,
Oct 4, 2022, 1:00:49 AM10/4/22
to hbrob...@googlegroups.com
It’s a year or 2 since I did this. This is the info I wrote up. It relates to the mini pc we are using on our robot, but the same technique should work on any pc. 

We found that the usb would move assignments until we locked them down as below:

  1. Statically assigning ttyUSB* devices to friendly names to use in ROS code


This is achieved by mapping the physical USB ports which are unique to the friendly names we will assign to the attached devices.


Below is the Hystou port mapping reference:

———————————————————————————

|    1-1        |    1-4        |    1-5.2        |

———————————————————————————

|    1-2        |    1-5.1        |    1-5.3        |

———————————————————————————


The above ascii diagram is a reference to the 6 physical USB ports, and the kernel assigned unique ID’s given to each port.


Using udev rule to statically assign these ports to friendly names:

$sudo nano /etc/udev/rules.d/99-usb-serial.rules

Paste the following lines into the new file:

KERNEL=="ttyUSB*", KERNELS=="1-5.1", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", SYMLINK+="rplidar"

KERNEL=="ttyUSB*", KERNELS=="1-2", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", SYMLINK+="megamcu"


Save the file.


A J

unread,
Oct 4, 2022, 4:51:32 PM10/4/22
to HomeBrew Robotics Club
The support people might be able to customize the id info.

https://www.silabs.com/interface/request-product-id

Steve " 'dillo" Okay

unread,
Oct 4, 2022, 10:08:45 PM10/4/22
to HomeBrew Robotics Club
On Monday, October 3, 2022 at 5:22:29 PM UTC-7 Michael Wimble wrote:
I now have two LIDARs in Puck, instead of one, and they are both identical pieces of hardware. When I plug them in, they get mounted as /dev/ttyUSB0 and /dev/ttyUSB1. But, as is usual for Linux, it is not stable as to which LIDAR gets mapped to which dev entry. And, if you unplug and replug either LIDAR, it gets assigned a different device name. This makes it impossible to write a script that correctly references a specific LIDAR using the /dev name entry.

You could try to match them off the Serial or iSerial attribute.

Add ATTRS{iSerial}="c0ffeed00d" (or whatever the serial number/UUID you get from the device for running lsusb -v) to your udev rule and that will make the devices unique.
udev rules will match against whatever unique attributes you can dig up about a device from either lsusb -v or udevadm info --attribute-walk

HTH,
'dillo



 
Reply all
Reply to author
Forward
0 new messages