ROSを使ってルンバが操作できるまで feat. Raspberry Pi3とPS4コントローラーとUSBカメラ

ROSでのルンバの制御はググればいろいろ情報が出てきますが、若干詰まった部分もあったので備忘録的な記事。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/196838/0bc15f69-205f-c312-d969-633a915581d7.png)



#環境とかいろいろ
・ラズパイ：Raspberry Pi3 Model B
・OS：Ubuntu Mate 16.04
・ROS：kinetic
・るんば：Roomba 621
・るんば制御用パッケージ：create_autonomy
・ノートPC：thinkpad x1, ubuntu 16.04

#ラズパイのセットアップ
## SDカードにubuntu-mateのイメージを書き込み

今回はROSメインでルンバを制御するのでOSはUbuntu-Mateを入れます。
下の記事を参照。操作はubuntu16.04が入ったthinkpad上で行っています。

＜Raspberry Pi3にUbuntu Mateをインストール＞
https://ubuntu-mate.org/download/

・Ubuntu Mateのイメージをダウンロード、解凍。
・SDカードを差し込む
・SDカードのマウント先を確かめる

```
$ lsblk
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/196838/32729471-5a5b-4ba4-6c41-6e0e48590abe.png)


16GのSDカードなので、/dev/sdbかな。
で、SDカードにosのイメージを書き込み。

```
$ sudo ddrescue -D --force ~/Downloads/ubuntu-mate-16.04.2-desktop-armhf-raspberry-pi.img /dev/sdb
```

・sdカードをラズパイに刺して起動
・とりあえず[sshを動かしておく](https://qiita.com/sasayabaku/items/ff96f700d2b65fdf085e)

```
$ sudo apt update
$ sudo apt upgrade
$ sudo apt-get install openssh-server
$ sudo /etc/init.d/ssh restart
```

・起動時にsshを自動起動させる

```
$ sudo systemctl enable ssh
```


#るんばのハードセットアップ

下の記事が最強だったので、とくに困らず。

＜ルンバをRaspberry Piを使ってROSでコントロールできるように改造してみた（半田付け無しでOK）＞https://karaage.hatenadiary.jp/entry/2017/05/12/073000

この記事はraspbian用なのですが、今はラズパイ用のubuntu mateが[公式](https://www.raspberrypi.org/downloads/)で出されているので、そちらを使います。記事がとても読みやすいので、raspiの場合は〜と書いてある部分を無視して進めばとりあえずok。

#るんば制御ノードのインストール

これも上の記事を参考に行います。

流れとしては
・[rosをインストール](http://wiki.ros.org/ja/kinetic/Installation/Ubuntu)
・ルンバ用のrosパッケージの"[create_autonomy](https://github.com/AutonomyLab/create_autonomy)"をインストール、ビルド、ソースする

```
$ cd ~/catkin_ws/src
$ git clone https://github.com/AutonomyLab/create_autonomy.git 
$ cd ~/catkin_ws
$ catkin_make -j2
$ source devel/setup.bash
```

ラズパイ３では通常４コア並列のビルドが走るみたいですが、メモリ不足でフリーズすることが多いので
-j2オプションを２コアに下げてます。

※catkin build推奨とありましたが、catkin_makeでもokでした。

・USBシリアル変換コネクタを通じてルンバとPCをつなぐ
・USBのアクセス権を付与

```
$ sudo chmod a+rw /dev/ttyUSB0
```

※毎回ttyUSB0するもの面倒なので、udevの設定がおすすめ。
（参考：https://qiita.com/caad1229/items/309be550441515e185c0）

・create_autonomyを実行

```
$ roslaunch ca_driver create_2.launch
```

※USBのアクセス権を与え忘れて、何度かエラーになったので注意。


最初はうまくるんばと繋がらず、ググりながらボーレートの値とかをいじっていたのですが、
シリアル通信のコネクタを付け間違えたいたのが原因でした。
RxDが受信、TxDが送信なんですね。シリアル通信したの初めてだったので、RxDをそのままRxDに繋いでました。






#PS4コントローラをubuntuに繋ぐ

PS4も下の記事を参考にセットアップ。

＜ROSでPS4のコントローラ(DualShock4)を使う方法＞
http://cryborg.hatenablog.com/entry/2016/09/19/185501

・ROS用のPS4コントローラドライバ

```
$ sudo apt-get install ros-<DISTRO>-joy
```

・bluetooth通信用のドライバ

```
$ sudo pip install ds4drv
```


・PS4コントローラと接続。USB接続の場合は直挿し。bluetoothの場合は

```
$ sudo ds4drv 
```

の後に、PS4のSHAREとPSボタンを長押し。

・PS4の接続先を確認

```
$ cat /proc/bus/input/devices | grep Sony -A 10 -B 2
```




手元のPCではUSBでPS4コントローラをつなぐと/dev/input/js1に、bluetoothでつなぐと/dev/input/js0に繋がる。
USBの時はジャイロとかのセンサー系の値と、スティックとボタンのデータがそれぞれjs0とjs1に別々に来ているっぽい。

今回はbluetooth接続メインで行くので、rosノードの引数にjs0を引数で与える。

・joyノードを起動

```
$ rosrun joy joy_node _dev:=/dev/input/js0 
```

でok.

#PS4の入力をルンバへ送る

先にインストールしたPS4の値を取り出すrosノードは、sensor_msgs::Joyというメッセージ型でトピックを出すけど、ルンバに送りたいトピックはgeometry_msgs::Twistなので、この変換ノードを作ります。

調べたら下の記事が出てきたけど、情報が古いのでセンサーの型が違うみたい。
＜PS3のコントローラーを使う＞
http://ros-robot.blogspot.com/2010/01/ps3.html

なので結局、参考にしながら自分で作成。
https://github.com/TakaHoribe/joy_to_twist

js0になるかjs1になるかの違いでjoyのメッセージが違うようなので、引数としてmodeが0か1かで分ける。
最初はUSB接続かbluetooth接続かでメッセージ型が違うのかとも思ったけど、ノートPC（ubuntu）でつなぐのとラズパイ（ubuntu mate）でつなぐのとで、同じUSB接続でも違いが出たので、ここは毎回確認しないとダメそう。


```
$ cd ~/catkin_ws/src
$ git clone https://github.com/TakaHoribe/joy_to_twist.git
$ cd ~/catkin_ws
$ catkin_make
```


js1接続の時はjoy.axesの中身が

[0] L stick horizontal
[1] L stick vertical
[2] L2
[3] R stick horizontal
[4] R stick vertical
[5] R2

という並び順だったけど、js0の場合は

[0] L horizontal
[1] L vertical
[2] R horizontal
[3] L2
[4] R2
[5] R stick vertical

となっている。。。（なぜ？）


#実際に動かす

１. ラズパイを起動してsshで繋ぐ
２. PS4コントローラをつなぐ：ps4とのbluetooth通信ドライバを起動

```
$ sudo ds4drv
```
　ps4コントローラのSHAREとPSボタンを同時に長押しでペアリングモードにして接続。
　接続先を確認する。

```
$ cat /proc/bus/input/devices
```

３. joyノードを起動（_devには上で確認した接続先を指定）

```
$ rosrun joy joy_node _dev:=/dev/input/js0
```


４．ルンバの電源を入れてから、ルンバ制御パッケージを起動

```
$ sudo chmod a+rw /dev/ttyUSB0 #USBの接続権限
$ roslaunch ca_driver create_2.launch
```


５. twist変換ノードを起動

```
$ rosrun joy_to_twist joy_to_twist _mode:=0
```

６. 遊ぶ


#その他

## USBカメラで画像を取得

会社の先輩から頂いたUSBカメラ（ありがとうございます）をラズパイに繋いで設定。
UVCに対応しているので一瞬で出来た。

以下の記事を参考

＜ROS KineticでのUSBカメラ接続とキャリブレーションまで＞
　https://qiita.com/proton_lattice/items/aa805b28700575ba5ed3

・USBカメラをつける
・USBカメラが接続されているか確認

```
$ lsusb
```

・rosのusbカメラ用パッケージをインストール

```
$ sudo apt-get install ros-kinetic-uvc-camera
```

・起動

```
$ roscore
$ rosrun uvc_camera uvc_camera_node
```

/image_rawというtopicが出ていればok. rvizで確認できる。

![Screenshot from 2018-07-01 18-19-33.png](https://qiita-image-store.s3.amazonaws.com/0/196838/a0251f41-ccae-de64-66d6-b2711a9e3360.png)



## ノートPCにトピックを送る。

ネットワーク間でのトピック通信を行う。
ノートPCからsshでラズパイに入って、ROS_HOSTNAMEとROS_MASTER_URIを設定する。

```
$ ssh <IP_RASPI3>
$ export ROS_HOSTNAME=<IP_RASPI3>
$ export ROS_MASTER_URI=http://<IP_RASPI3>:11311
```

ノートPC側でも同様にROS_MASTER_URIをラズパイのipアドレスに設定する。
※各ターミナルで実行する必要がある。面倒だったら~/.bash.rcに書き込む。


#　残課題

・usbカメラとルンバコントロールのノードを同時に起動すると、/joyにノイズが入って、ルンバがたまにカタカタする。
・顔認識させたいけどラズパイで動くのかな？


# メモ

`ds4drv`が上手く動かないことがあった。こんなエラーを吐く。

```
ImportError: /usr/local/lib/python2.7/dist-packages/evdev/_ecodes.so: nonzero padding in e_ident
```

`ds4drv`を再インストールしたら復活した。

```
$ sudo -H pip --no-cache-dir install -I ds4drv
```