Please ask about problems and questions regarding this tutorial on answers.ros.org. Don't forget to include in your question the link to this page, the versions of your OS & ROS, and also add appropriate tags. |
Using multiple cameras
Description: Describes how to set up udev rules and launch files to use several robotino_camsKeywords: Robotino, USB Camera, Webcam, udev
Tutorial Level: BEGINNER
Preparations
The first thing to do in order to use the robotino_cam is to check it out and build it.
rosdep install robotino_cam rosmake robotino_cam
Then of course you need several USB cameras attached to Robotino or your PC. It's easiest to use several different models at first, since unfortunately some webcams can't be distinguished by software, as we will see later.
Configuring a launch file
The simplest way to launch several cameras is a launch file. Let's have a look at this example, working with two cameras:
1 <launch>
2 <node ns="cam0" name="robotino_cam" pkg="robotino_cam" type="robotino_cam_node">
3 <param name="camera_index" value="0" />
4 </node>
5 <node ns="cam1" name="robotino_cam" pkg="robotino_cam" type="robotino_cam_node">
6 <param name="camera_index" value="1" />
7 </node>
8 </launch>
What does it do? It starts two robotino_cam_nodes, each in it's own namespace. This way, we can easily distinguish between both nodes without the need to remap any topic or parameter.
To actually read the images from different cameras, we need to set one parameter for each camera:
3 <param name="camera_index" value="0" />
The camera_index defines, which camera to use. Default is -1, with which the node will choose a camera by itself, the range 0 through 7 directly refer to the devices /dev/video[0-7].
Remapping the cameras with a udev rule
Unfortunately the order of those devices is determined by the order, the cameras were loaded or plugged in, so this can lead to strange effects, when e.g. the left camera usually gets loaded before the right camera, but not always. So you might want to map the cameras to other devices based on their model ID or serial number. To do this, you need to first get some information on your camera you can use to identify it. So plug the camera to your computer (wait a little to allow the system to recognize it) and run the following command:
sudo sh -c 'lsusb -v | more' or sudo lsusb -v > some/file.txt
Usually devices like a webcam appear on top of the following list, so the "| more" should be fine, otherwise store it in a file to have a look at it. The section you're looking for should look similar to this:
Bus 001 Device 014: ID 046d:0991 <nice name of your webcam> Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 2.00 bDeviceClass 239 Miscellaneous Device bDeviceSubClass 2 ? bDeviceProtocol 1 Interface Association bMaxPacketSize0 64 idVendor 0x12cd <company name> idProduct 0xfe98 <Model name> bcdDevice 0.08 iManufacturer 0 iProduct 0 iSerial 2 1A2B3C4D bNumConfigurations 1 Configuration Descriptor: ...
The most important line is the one containing the serial number (the first "2" is not part of the serial):
iSerial 2 1A2B3C4D
The problem is, for some devices this line only contains a zero, since they don't provide their serial number. If this is the case, you can still use this camera, but only a single one per PC, since you have nothing else to identify it besides the model ID.
Now you can set up a udev rule to map any video device with this serial/model number (i.e. this webcam) to a specific device, e.g. from /dev/video0 to /dev/my_webcam. But there is another restriction, since robotino_cam is based on OpenCV, which in turn only accepts indices and therefore the devices /dev/video[0-7], so you need to map your camera to a video#-device. The best way to do this is to start at video7 counting down to avoid conflicts with real devices. Create a textfile in /etc/udev/rules.d with a filename like "10-my-webcam.rules". Important parts are the number at the beginning (have a look at the README-file in that directory, but 10 is a good idea) and the extension ".rules". The contents of this rules-file should look a lot like this:
# it's a good idea to use commentaries to identify the devices for humans BUS=="usb", KERNEL=="video*", SYSFS{serial}=="1A2B3C4D", SYMLINK+="video7" BUS=="usb", KERNEL=="video*", SYSFS{idProduct}=="fe98", SYMLINK+="video6"
Let's have a closer at the elements. BUS=="usb" We are talking abount a USB device... KERNEL=="video*" ...that is usually mapped to something like /dev/video*... SYSFS{serial}=="1A2B3C4D" ...with this serial number (or model ID). SYMLINK+="video7" We want to create a link to it named "/dev/video7".
The next time you plug in your camera, you should see the freshly created link, so now you can change your launch file to these indices and never care about the loading order again.
You might want to have a deeper look into udev and it's mapping rules, since there are a lot more things, you can do with it. The wiki page of the hokuyo_node also features a very short example on udev usage.