MATLABのRaspbianイメージを使ってMac上にROS on Raspi開発環境を構築する

## MATLABのROS on Raspbian開発環境

今回はMATLABのRasPiの拡張機能を使った開発環境構築について書きたいと思います。
通常、MATLABでRasPiの拡張機能を使う場合、MathWorksが提供しているRasbianのSDイメージか、Ubuntu環境を使っている方が多いと思います。
ただ、Ubuntu環境は一癖あるということで、ほとんどの人がRaspbianで動かしていると思います。
毎回、Raspberry PiのSDカードをRaspbianに入れ替えてMATLABで開発というのも使いにくい。。。ということで、今回Mac上でMathWorkの提供するRaspbianの環境を作って、仮想RasPiで開発できるようにしていきます。

## 準備

必要なもの

- とりあえずARM64のMac
- Docker Imageを作成するためのUbuntu PC
- Docker Desktop
- MATLAB/Simulink homeライセンス
- ROS Toolbox

## セットアップ 

次の設定やインストールを済ませておきます。

- Docker Desktopのインストール
- MATLAB/Simulinkのインストール（R2021a）
- MATLAB/SimulinkのRasPi拡張機能（MATLAB用Simulink用のどちらも）のインストール

### x86_64のbrewを使ってpython2をインストール

MATLABにはrosinitコマンドでroscoreが立ち上げられるようになっています。しかし、armのMacでは、Rosetta上で動いているため、x86_64で立ち上がります。rosinitにはpython2が必要なことから、python2をインストールしていきます。

#### MacのリモートログインをOFF

今回Dockerの中のRaspbianに対してsshを行えるようにするため、HostのMacのsshdは停止する必要があります。ですので、まずはMacの設定の共有にあるリモートログインが無効になっているか確認します。

#### x86_64のターミナルを準備

Terminal.appをコピーして、Teminali386.appを作成し、その設定で以下のようにRosettaで開くにチェックを入れておきます。このアプリから実行すると常にx86_64で立ち上がるようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/6ece913c-fcf5-726d-ce7e-d2934bebfebd.png)

続いて、x86_64用のbrewをインストールし、python2を入れていきます。

brew install
```
arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```

python2のインストール

```
brew install pyenv
pyenv install 2.7.18
pyenv global 2.7.18
```

続いて、MATLABを立ち上げます。
以下のコマンドでpythonの場所を指定します。

```
pyenv('Version','/Users/ユーザー名/.pyenv/shims/python')
```

ここでrosinitを実行するとエラーで実行できません。。。みなさんよくご存知のMATLABのバグです。。。理由はnetifacesが対応するバージョンがarmのMacに対応したものが入っていないのが原因です。
ですので以下からnetifaces-0.11.0.tar.gzをダウンロードします。
https://pypi.org/project/netifaces/#files
そして、以下のコマンドで、MATLABの中にコピーします。

```
cp ./netifaces-0.11.0.tar.gz /Applications/MATLAB_R2021a.app/sys/ros1/share/python/
```

この状態で、rosinitを実行するとMATLAB内でroscoreが立ち上がります。

### RaspbianのイメージファイルからDocker imageを作成する

ここから、MATLABのRaspbianイメージをDockerで使えるようにしていきます。
やることは単純で、Ubuntu PCでMATLABのRaspi拡張機能でダウンロードしたimageファイルをマウントするところから作業をします。

Ubuntu PCでMATLAB Raspbianのイメージファイルをダブルクリックすると自動で、bootとrootfsがマウントされます。rootfsに移動して、tarballを作成するだけです。

```
cd /media/ユーザー名/rootfs
sudo tar cvf ~/matlab_raspbian.tar ./
```

ここで作成したtarballをMacに持っていけば準備は完了です。

## 環境構築

まず、以下のGitHubからリポジトリをクローンしてきます。

```
git clone https://github.com/tatsuyai713/matlab-raspi-devenv
cd  matlab-raspi-devenv
```

先ほど用意した、tarballをDockerに取り込んでいきます。

```
docker image import ~/matlab_raspbian.tar raspi_docker_image:latest
```
続いて、以下のコマンドで、Dockerfileをビルドして、コンテナを作成します。

```
./launch_container.sh build
```

これが完了すると自動でRaspbianの中にログインします。この中でいろいろ作業ができるようになっており、環境を保存するにはexitしてから

```
./launch_container.sh commit
```

でコミットすることができます。
２回目からは、

```
./launch_container.sh
```

で、もう一度Container内に入って作業することができます。

新しくターミナルを立ち上げて、

```
ssh pi@localhost
```
を行うことで、Containerの中にsshで入れることを確認します。

これで開発環境構築は完了です。

## ROSのコード生成をDockerの仮想RasPiで実行する

まず、MATLAB内でrosinitでroscoreを立ち上げておきます。というのもMATLAB/SimulinkでROS Toolboxを使用するためには、roscoreが立ち上がっていないといけないのですが、Mac上でroscoreを立ち上げるのは大変なので、MATLAB内のroscoreを使います。

続いて、以下のような適当なROSを使ったSimulinkモデルを作ってみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/5fa1216e-723e-7bb4-0fc1-0e555f4970ec.png)

ROSを使えるように以下のように設定をしていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/4aa53a23-ac3e-42cb-c06f-42f6ee883a98.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/840e9a70-d4e6-6839-dc04-ce72083f1430.png)

ここまでできれば、最後に、ビルドと配布を実行するとROSのノードが作成されます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/586d5f0b-895a-4406-921d-1b6f888839c2.png)


そして、./launch_container.shを実行しているターミナルか、ssh pi@localhostでログインして、

```
cd ~/catkin_ws
source ./devel/setup.bash
roscore
rosrun untitled untitled_node
```

これで、ビルドしたROSノードが実行できます！

## まとめ

今回は、MATLAB/SimulinkでROSノードをビルドして実行するのを、Docker上のRaspbianで実行する環境を作りました。これがあればRasPiがなくてもコード生成を試すことができます。しかしながら、この環境の問題点は、Dockerのネットワーク内でしか実行できない（Dockerのコンテナのネットワークは外から見えない）ので、あくまでMATLAB/Simulinkの動作確認レベルしかできないですが、これで開発して実機を繋げる時は、実機に接続を変えて使うという使い方ができます。ではでは、また次回に。