Raspberry Pi 4 + ROS2 で、最低限のロボットプログラムを作る準備

# （2020/4/28 追記）
Raspberry Pi 4 用の Ubuntu 18.04 公式イメージが使用可能になっていました。
しかし、今は 20.04 の陰に隠れているようです...。
おそらく、ここからダウンロードできます。
http://cdimage.ubuntu.com/releases/18.04.4/release/
 
2020年5月23日に、Ubuntu 20.04 対応の ROS2（foxy）がリリースされます。
**それ以降は、Ubuntu 20.04 + ROS2（foxy）の使用を推奨します。**
Ubuntu 20.04 は既に Raspberry Pi 4 に対応済です。



# はじめに

Raspberry Pi 4 に ROS2 を入れて、最低限のロボットプログラム（Python）を動かす準備をします。
雑に「ロボット」と言ってしまいましたが、GPIO経由でのセンサ読み取りやサーボモータ制御するだけです。

~~残念ながら、Raspberry Pi 4 で ROS2 を使う公式な方法がまだありません。~~
~~私は以下の方法で一時しのぎしながら、公式リリースを待ちます...。~~

## すること
- Raspberry Pi 4 で ubuntu 18.04 を起動
- ROS2 のインストール
- I2C の有効化 → サーボドライバPCA9685 の利用準備
- GPIO の利用準備

「ハードはどうでもいいからソフトだけ動かしたい」って人は最初の2つだけでOKです。

# Raspberry Pi 4 で Ubuntu 18.04 を起動
（追記 に記載した、公式イメージを使用することを推奨します。）

~~Raspberry Pi 4 に公式で対応しているのは Ubuntu 19.10 になります。~~
~~しかし、ROS2 は今のところ Ubuntu 18.04 までしか対応しておらず...。~~
~~探したところ、非公式で Raspberry Pi 4 用の Ubuntu 18.04 イメージを公開している人がいたので、それを利用させてもらいます。~~



1. ~~[このページ](https://blog.cloudkernels.net/posts/rpi4-64bit-virt/)の最後のリンクから~~  
~~ubuntu-18.04.3-preinstalled-server-arm64+raspi4+kvm.img.xz~~  
~~をダウンロード（raspi3用のものと間違えないよう注意）~~  
[こちら](http://cdimage.ubuntu.com/releases/18.04.4/release/)から  
Raspberry Pi 4 用の Ubuntu 18.04.4 LTS（64bit） をダウンロード
2. これを [Etcher] (https://www.balena.io/etcher/) などでSDカードに書き込み

これで、とりあえずは Raspberry Pi 4 で Ubuntu 18.04 が動きます。
SSHなどで接続してログインしましょう。
（初期user、初期password はともに "ubuntu"）



# ROS2 のインストール
[公式ページ](https://index.ros.org/doc/ros2/Installation/Dashing/Linux-Install-Debians/)に従えばサクッと終わります。

```
# https://index.ros.org/doc/ros2/Installation/Dashing/Linux-Install-Debians/

## （en_US ではなく ja_JP でもOK）
$ sudo locale-gen en_US en_US.UTF-8
$ sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
$ export LANG=en_US.UTF-8

$ sudo apt update && sudo apt install curl gnupg2 lsb-release
$ curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | sudo apt-key add -

$ sudo sh -c 'echo "deb [arch=amd64,arm64] http://packages.ros.org/ros2/ubuntu `lsb_release -cs` main" > /etc/apt/sources.list.d/ros2-latest.list'

$ sudo apt update

## （デスクトップ版を使いたければ、ros-dashing-desktop に変更してください）
$ sudo apt install ros-dashing-ros-base

$ sudo apt install python3-argcomplete
$ sudo apt install python3-colcon-common-extensions python3-pip python-rosdep python3-vcstool

$ source /opt/ros/dashing/setup.bash
$ echo "source /opt/ros/dashing/setup.bash" >> ~/.bashrc
```

# I2C の有効化（PCA9685 の利用準備）
サーボドライバ（PCA9685）でサーボを動かすための準備。
I2Cを使わない人は飛ばしてOKです。

## I2Cの有効化
Raspberry Pi で I2C通信ができるように設定変更。
/boot/firmware/config.txt のこの行のコメントアウトを外してください。

```/boot/firmware/config.txt
# dtparam=i2c_arm=on
```

続いて、/etc/modules の最後に次の2行を追加します。

``` :/etc/modules
i2c-bcm2708
i2c-dev
```

必要なものを入れておきます。

```
$ sudo apt install i2c-tools
$ sudo apt install python3-smbus
```

## PCA9685 を動かす準備
Python3 から動かすためのライブラリをインストール。

```
$ sudo pip3 install adafruit-pca9685
```
残念ながら、このままではエラーが出て使えません。
[この記事](https://kokensha.xyz/jetson/jetson-nano-pca9685-i2c-error-resolution/)を参考に、ライブラリを修正します。
/usr/local/lib/python3.6/dist-packages/Adafruit_GPIO/I2C.py のこの関数を修正。

```Python:/usr/local/lib/python3.6/dist-packages/Adafruit_GPIO/I2C.py
def get_i2c_device(address, busnum=None, i2c_interface=None, **kwargs):
    """Return an I2C device for the specified address and on the specified bus.
    If busnum isn't specified, the default I2C bus for the platform will attempt
    to be detected.
    """
    ### ここをコメントアウト ######
    # if busnum is None:
    #    busnum = get_default_bus()
    # return Device(address, busnum, i2c_interface, **kwargs)
    #########################

    ### これを追記
    return Device(address, 1, i2c_interface, **kwargs)
```

I2Cプログラムを動かすとき、毎回sudoしなくてもいいように以下を実行。
（ubuntuはユーザ名）

```
sudo usermod -aG i2c ubuntu
```

# GPIO の利用準備
[ここ](http://abyz.me.uk/rpi/pigpio/download.html)を参考に、pigpioをインストール。

```
## 念のため
$ sudo apt install python-setuptools python3-setuptools

$ wget abyz.me.uk/rpi/pigpio/pigpio.zip
$ unzip pigpio.zip
$ cd PIGPIO
$ make
$ sudo make install
```

# 終わりに
Raspberry Pi 4 で ROS2 および最低限のハードウェアを動かす準備ができました。
次回は、この環境を使って小さなロボットプログラムを作成します。