ROSのカメラノードを複数同時に立ち上げる

複数のカメラを同時に起動して映像を受信したかったので、調べながら行ったことを自分の備忘録として書き記しておきます。

# 環境
・VMware Workstation Player
・Ubuntu18.04
・ROS Melodic

# 使用するUSBカメラについて
なんでも大丈夫です。
当記事では[SEW11-2K370WL](https://www.amazon.co.jp/SUNEAST-WEB%E3%82%AB%E3%83%A1%E3%83%A9LED%E3%83%A9%E3%82%A4%E3%83%88-zoom%E4%BC%9A%E8%AD%B0%E7%94%A8PC%E3%82%AB%E3%83%A1%E3%83%A9-Limux%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0-Youtube%E5%AF%BE%E5%BF%9CSEW11-2K370WL/dp/B096S4YX1P/ref=sr_1_5?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=SEW11-2K370WL&qid=1636182176&sr=8-5)というWebカメラを2台使用します。

# 必要なパッケージのインストール

```terminal:
$ sudo apt install ros-melodic-uvc-camera
$ sudo apt install ros-melodic-image-*
$ sudo apt install ros-melodic-image-view
$ sudo apt install v4l-utils
```

# USBカメラのキャリブレーション
[こちら](https://qiita.com/srs/items/416aa78f2c679ddb7c52)の記事などを参考に、必要に応じてUSBカメラのキャリブレーションを行ってください。

# カメラ情報の確認
下記のコマンドを入力してカメラがどこにマウントされているのかを調べます。

```
$ v4l2-ctl --list-devices


WEB CAM: WEB CAM (usb-0000:03:00.0-2):
	/dev/video0
	/dev/video1

WEB CAM: WEB CAM (usb-0000:03:00.0-4.1):
	/dev/video2
	/dev/video3
```
私の環境では<b>/dev/video0</b>と<b>/dev/video2</b>にマウントされているのが分かりました。
<br>
次に、使用するカメラで扱えるパラメータを調べます。
異なるカメラを2台使用している場合、ポート名の部分をもう1台のカメラがあるところに変更して再度実行してください。（私の場合だと/dev/video2になります。）
同じカメラを2台使用している場合はどちらか一方でのポート名でのコマンドで大丈夫です。

```terminal:
$ v4l2-ctl -d /dev/video0 --list-formats-ext


ioctl: VIDIOC_ENUM_FMT
	Index       : 0
	Type        : Video Capture
	Pixel Format: 'MJPG' (compressed)
	Name        : Motion-JPEG
		Size: Discrete 1920x1080
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 1440x1080
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 1280x720
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 800x480
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 640x480
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 3840x2160
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 640x360
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 800x600
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 2560x1440
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 2592x1944
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 1920x1080
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.033s (30.000 fps)

	Index       : 1
	Type        : Video Capture
	Pixel Format: 'YUYV'
	Name        : YUYV 4:2:2
		Size: Discrete 1280x720
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 800x480
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 640x480
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 320x240
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 640x360
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 800x600
			Interval: Discrete 0.033s (30.000 fps)

	Index       : 2
	Type        : Video Capture
	Pixel Format: 'H264' (compressed)
	Name        : H.264
		Size: Discrete 1920x1080
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 1440x1080
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 1280x720
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 800x480
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 640x480
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 320x240
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 640x360
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 800x600
			Interval: Discrete 0.033s (30.000 fps)
```
uvc_cameraのデフォルトのピクセルフォーマットはYUYVなのですが、YUYV形式で2つもカメラノードを立ち上げると映像の転送容量が大きくなり、fpsが低下する場合があります。
このカメラではピクセルフォーマットがMJPGの時に1980×1080で30fps出せることが分かったので、この値を使用することにします。

# launchファイルの作成
1つのコマンドで2つのカメラノードを同時に立ち上げられるようにするために、launchファイルを作成します。
下記のコマンドでlaunchファイルを作成します。エディタは何でも大丈夫です。

```terminal:
$ cd /opt/ros/melodic/share/uvc_camera/launch
$ sudo gedit two_cameras.launch
```
<br>
下記の内容をコピーし、解像度やfpsの部分等は自分が使っているカメラにあったものに変更して貼り付けてください。
このlaunchファイルでは2つのカメラの名前をそれぞれcamera_rightとcamera_left、フォーマットをMJPG、解像度を1920×1080、30fpsに設定しています。

```xml:two_cameras.launch
<?xml version="1.0"?>

<launch>
    <group ns="camera_right">
        <node pkg="uvc_camera" name="camera0" type="uvc_camera_node" output="screen">
            <param name="device" type="string" value="/dev/video0"/>
            <param name="width" type="int" value="1920"/>
            <param name="height" type="int" value="1080"/>
            <param name="fps" type="int" value="30"/>
            <param name="format" value="jpeg"/>
            <param name="frame_id" value="camera_right"/>
        </node>
    </group>


    <group ns="camera_left">
        <node pkg="uvc_camera" name="camera1" type="uvc_camera_node" output="screen">
            <param name="device" type="string" value="/dev/video2"/>
            <param name="width" type="int" value="1920"/>
            <param name="height" type="int" value="1080"/>
            <param name="fps" type="int" value="30"/>
            <param name="format" value="jpeg"/>
            <param name="frame_id" value="camera_left"/>
        </node>
    </group>
</launch>
```

# カメラ映像の確認
ちゃんとカメラノードが2つ立ち上がっているか確認します。
ターミナルを新しく3つ開き、下記のコマンドをそれぞれ入力してください。

```terminal:ターミナル1
$ roscore
```
```terminal:ターミナル2
$ roslaunch uvc_camera two_cameras.launch
```
```terminal:ターミナル3
$ rostopic list


/camera_left/camera_info
/camera_left/image_raw/compressed
/camera_right/camera_info
/camera_right/image_raw/compressed
/rosout
/rosout_agg
```
<br>
camera_leftとcamera_rightの両方が存在しているのが分かります。
<b>/camera_left/image_raw/compressed</b>と<b>/camera_right/image_raw/compressed</b>がカメラ映像です。
<br>
実際に映像を見てみます。
下記のコマンドで映像を見ることができます。

```terminal:ターミナル3
$ rqt_image_view
```
<br>
左上のドロップダウンリストから/camera_left/image_raw/compressed及び/camera_right/image_raw/compressedを選択することで映像を確認することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669160/abcf1cc8-6714-e7ba-9eb7-3faaaeab984b.png)

# 参考・リンク
[ROS KineticでのUSBカメラ接続とキャリブレーションまで](https://qiita.com/proton_lattice/items/aa805b28700575ba5ed3)
[ROS講座66 カメラのキャリブレーションを行う](https://qiita.com/srs/items/416aa78f2c679ddb7c52)
[USBカメラが使えない #52](https://github.com/Nishida-Lab/rosbook_pkgs/issues/52)
[uvc_camera ROS Wiki](http://wiki.ros.org/uvc_camera)