ROSの勉強　第40弾：USBカメラ

# #プログラミング ROS< USBカメラ >

##はじめに
2つ目の参考書に沿って，ROS(Robot Operating System)をさらに扱えるようになることが目的である．ROSの学習としては継続するため，その第40弾として，「USBカメラ」を扱う．

##環境
#####コンピュータ
|||
|:-:|:--|
|デバイス|raspberry pi 4 Model B|
|メモリ|3.7 GiB|
|Graphics|V3D 4.2|
|OS|Ubuntu|

#####Ubuntu
|||
|:-:|:--|
|リリース|20.04.2 LTS (Focal Fossa) 64ビット|
|カーネル|Linux 5.4.0-1035-raspi aarch64|
|MATE|1.24.0|

#####ROS
|||
|:-:|:--|
|Distribution|noetic|

#####USBカメラ
|||
|:-:|:--|
|メーカー|Buffalo|
|シリーズ|BSWHD06M|


##必要なドライバのインストール
ここでは，必要なドライバとして，USBカメラでキャプチャするための「usb_cam」ノードとキャプチャした画像を表示させる「image_view」ノードとする．

```:install
sudo apt install ros-noetic-usb-cam
sudo apt install ros-noetic-image-view
```

##ノードの起動
まず，複数のノード間でデータのやり取りをするので，マスタを起動しておく．

```:materの起動
roscore
```

```:usb-cam
rosrun usb_cam usb_cam_node
```
このノードでは，カメラのポート割当がデフォルトでは，``/dev/video0``である．ほかのポートを指定したい場合は，以下のようにノードを起動させることも可能．

```:usb-cam（ポート変更）
rosrun usb_cam usb_cam_node _video_device:=/dev/video1
```
なお．raspberry piにUSBカメラだけつけている場合は，``/dev/video0``であったため，この操作は不要であった．ここで，どのポートがあるかを調べるコマンドを示しておく．

```:/dev/video探索
ls /dev/video*
```
0の代わりにワイルドカード(*)をつけることで，videoポートが複数あったときにすべて確認することができる．

* USBカメラを接続する前
![video_port_before.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951300/37f5fb02-52ee-4b22-0a00-a5e9b66a985f.png)

* USBカメラを接続した後
![video_port_after.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951300/979d2e15-7c8c-c05c-f64f-97033419245b.png)

/dev/video0がUSBカメラに使えそうだ．なぜ，/dev/video1も出てくるのか，またカメラの機能の無い状態で/dev/video10~が存在するのかは，理解できていない．


続いて，キャプチャした画像を表示させるためのノードを起動

```:image-view
rosrun image_view image_view image:=/usb_cam/image_raw
```
image-viewでは，どのキャプチャ画像を表示するかを指定する必要がある．ここで行われていることは，次のとおりである．usb-camによりキャプチャされた生データ（画像）をusb-cam-nodeが配信しており，その配信されているデータをimage-viewが購読して，そのデータを表示してくれる．


##ノードのパラメータ設定
usb-cam，image-viewにはいくつものパラメータが存在し，細かな指定が可能となっている．これらのパラメータはlaunchファイルを用いることで，簡単に指定することができる．以下にそのlaunchファイルを示す．なお，各パラメータの説明については，launchファイル内でコメントする形で示している．

```xml:usb_cam.launch
<launch>
    <!-- usb_acmノードを実行する -->
    <node name="usb_cam" pkg="usb_cam" type="usb_cam_node" output="screen">
        <!-- カメラの指定　defaultは/dev/video0 -->
        <param name="video_device" value="/dev/video0"/>
        <!-- 画像の大きさ（横幅）の指定 -->
        <param name="image_width" value="640"/>
        <!-- 画像の大きさ（縦幅）の指定 -->
        <param name="image_height" value="480"/>
        <!-- 画像フォーマット設定　"mjpeg" or "yuyv" or "uyvy" -->
        <param name="pixel_format" value="mjpeg"/>
        <!-- fpsの指定　frame per second -->
        <param name="framerate" value="30"/>
        <!-- コントラストの設定（色設１） -->
        <param name="contrast" value="32"/>
        <!-- 明るさの設定（色設２） -->
        <param name="brightness" value="32"/>
        <!-- 彩度の設定（色設３） -->
        <param name="saturation" value="32"/>
        <!-- 自動フォーカス機能の設定　ブール値 -->
        <param name="autofocus" value="true"/>
        <!-- フォーカス位置の設定 -->
        <param name="focus" value="51"/>
    </node>

    <!-- image_viewノードを実行する -->
    <node name="image_view" pkg="image_view" type="image_view" respawn="false" output="screen">
        <!-- image_viewのimageトピックがimage_rawトピックをサブスクライブするように指定 -->
        <remap from="image" to="/usb_cam/image_raw"/>
        <!-- 画像の縦横比を自動で判定して表示 ブール値 -->
        <param name="autosize" value="true"/>
    </node>
</launch>
```
##実行結果
####no launch
![cam.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951300/0807bdca-e744-a7d4-7783-38067fe3867c.png)
画像ウィンドウの後ろに少し見えるが，このときターミナル（端末）はroscore, usb_cam_node, image_view_nodeの3つを動かしている．

####launch
![cam_launch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951300/0a26ed61-63a1-97d5-4c21-184f3d4dfc1f.png)
ターミナル（端末）1つで動かせるとともに，細かな変更までできるようになった．ここでは，少しコントラストが大きいと感じられる画像を取得するようになっている．

##感想
とりあえず，ROSでのカメラの扱い方について学ぶことができた．これにより，ROS上でも現実世界の画像を取得できるようになった．これにOpenCVなどを適用することで，画像処理も可能となり，ROSの可能性がさらに広がったと思う．

##参考文献
実用ロボット開発のためのROSプログラミング
　　　　　　　　西田 健，森田 賢，岡田 浩之，原 祥尭，
　　　　　　　　山崎 公俊，田向 権，垣内 洋平，大川 一也，
　　　　　　　　斎藤 功，田中 良道，有田 裕太，石田 祐太郎 共著
　　　　　　　　　　　　　　　　　　　　 森北出版株式会社　発行