(!) 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_cams

Keywords: 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.

   1 ...
   2     <param name="camera_index" value="7" />
   3 ...

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.

Wiki: robotino_cam/Tutorials/Using multiple cameras (last edited 2010-06-08 13:52:05 by RalfStauder)