Apple Silicon MacでもROSでgazeboとUSBデバイスを全部使いたい！

## はじめに
ROSの開発環境を利用する際には基本的にUbuntu（場合によってWSLやWindows Native）が必要ですが，M1 Macでも開発を行いたい需要は確かに存在すると思います．これに対して例えばTiryohさんはDocker＋ブラウザを利用する[[ROS/ROS2のGUIをWebブラウザ経由でお手軽に試せるDockerfileを公開しました]](https://memoteki.net/archives/2955#index_id2)の方法を公開しています．私も非常にお世話になりました．

シミュレーションのみの利用や簡単な動作確認などであれば非常に強力な方法ですが， **Macに接続したUSBデバイスを直接利用できない**という課題がありました．これはM1 Mac上で動作するDockerの制約に起因するもので，どうやらこのDockerがそもそもUSBデバイスを掴みに行けないことが原因のようです（違ったらごめんなさい，コメントで教えてください）．

私はPCへサーボをUSBシリアルデバイスとして接続して実機を動かしたいタイプのロボット屋さんなので，これを解消すべく本記事を書いています．M1 MacBook Pro 14 inchiで動作を確認していますが，ご自身の環境で利用される際の責任は負い兼ねますのでご了承ください．

**2024年6月6日追記**
M3 MacBook Pro 14 inchiでも利用可能なことを確認しました．


## 1. UTMで仮想Ubuntu環境を用意する

### UMTのインストール
UTMは[ここ](https://docs.getutm.app/installation/macos/)から落としてインストールします．GitHub版もApp Store版も機能は同じようです．App Store版はお布施の気持ちが乗せられるのと，自動更新が効くそうなのでお好みで選択してください．

### 仮想Ubuntu環境の構築

**Ubuntu22.04のインストール**

（2024年6月6日追記）
'24年6月時点では，UTMギャラリーでUbuntu22.04 Desktopの仮想マシンイメージが配布されています．
こちらを利用すればダウンロードしてUTMから開くだけで以降のubuntu serverのインストール→desktopの後入れが必要なく，とても便利です．

リンク: https://mac.getutm.app/gallery/ubuntu-20-04

**Ubuntu Serverのインストール**
UTM公式の[このページ](https://docs.getutm.app/guides/ubuntu/#downloads)の手順に沿って行えばOKです．UbuntuのISOイメージは予めDownloadsに書いてあるUbuntu Server for ARMをダウンロードしておきましょう．

私は作成時の設定を以下で行いました．
- メモリサイズの指定：とりあえず初期値(4096MB)
- ストレージサイズ：とりあえず初期値(64GB）

試される際は使用用途に合わせてお好みで変更してください．

[公式サイトの手順](https://docs.getutm.app/guides/ubuntu/#creating-a-new-virtual-machine)ではこの後に仮想マシンを再起動するよう指示がありますが，素直に仮想マシン内から再起動を行うと失敗するためUTMのウィンドウをXボタンで閉じて強制終了します．このとき，強制終了→光学ドライブの指定からUbuntuのOSイメージを削除→仮想マシンON の順番で進めます．

**Ubuntu Desktopのインストール**

Ubuntu Serverを起動してログインできたら，下記コマンドでUbuntu Desktopをインストールします．

```bash
sudo apt update
sudo apt install ubuntu-desktop
sudo reboot
```
### Docker環境の構築

Docker公式の[このページのaptの節](https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository)の手順に沿って行えばOKです．

### dockerをsudu無しで実行できるようにする
この[Qiita](https://qiita.com/DQNEO/items/da5df074c48b012152ee)を参考に行います．設定後に仮想Ubuntuを再起動しましょう．

### brlttyを削除する．
brltty（点字ディスプレイサポート）がシリアルデバイスを`/dev/ttyUSB0`としてマウントする際に阻害することがあるため削除しておきます（[参考](https://qiita.com/74th/items/f46bccd67b2ed6fc867f)）．
```bash
sudo apt remove brltty
```

## 2. ARM向けROS NoeticのDockerコンテナを起動する

### Workspaceの作成

以下の構成になるようにディレクトリを作成します．

```
YOUR_WORKSPACE/
    |-- YOUR_CATKIN_WS
    |-- docker_ros (次節でcloneします）
```

ここで，`YOUR_WORKSPACE`は任意のワークスペース名，`YOUR_CATKIN_WS`は使いたいcatkin_wsの名前とします．本記事ではこれ以降，例として`YOUR_CATKIN_WS`を`work_noetic`，`YOUR_CATKIN_WS`を`catkin_ws`とします．
このとき，以下のコマンドでディレクトリを作成できます．

```
cd ~
mkdir -p work_noetic/catkin_ws
```

以降の開発作業はここで作成したcatkin_wsを利用してください．

### Dockerfileのリポジトリをcloneする

まずは仮想マシン内でSSHキーの登録が必要です．SSHが使えるようになれば，cloneは次のコマンドで行えます．`-b noetic_arm`でARM向けのブランチを指定していることに注意してください．

```
cd ~/work_noetic
git clone https://github.com/kim-xps12/docker_ros -b noetic_arm
```

ここまでの手順を行い，以下のディレクトリ構成になっていることを確認します（ディレクトリ名は適宜読み替えてください）．
```
work_noetic/
    |-- catkin_ws
    |-- docker_ros
```
また，ここでcatkinのワークスペースを`catkin_ws`以外の名前で作成した場合は，`docker_ros/docker-compose.yml`[16行目のコロンより左側](https://github.com/kim-xps12/docker_ros/blob/noetic_arm/docker-compose.yml#L16)を適宜変更してください．
コンテナ起動時のマウントに失敗する恐れがあります．

### Dockerコンテナを起動する
以下のコマンドで行えます．初回実行時はOSイメージのダウンロード等が生じて時間がかかることもあるので，気長に待ちましょう．お使いのワークスペース名が`work_noetic`でない場合は適宜読み替えてください．

```bash
cd ~/work_noetic/docker_ros/
docker compose up -d
docker attach mynoetic
```

### Dockerコンテナ内からのGUIアプリの呼び出し確認
以下のコマンドでマウスカーソルに追従する目のGUIが起動すればOKです．
```bash
xeyes
```

### Dockerコンテナ内からのOpenGLの呼び出し確認
以下のコマンドで歯車が回るアニメーションが起動すればOK．
```bash
glxgears
```
ここまでの動作確認が通れば，rvizやgazeboがコンテナ内で起動できるはずです．

### USBシリアルデバイスの接続

使いたいUSBデバイスをMacに接続します．UTMから「USBデバイスを仮想マシンからマウントするか？」の旨のポップアップが表示されるため，これを許可すればOKです．少し待つと， `/dev/ttyUSB0`として認識されているでしょう．dialoutグループの設定はDockerfile内に記述しているのでそのまま利用できます．

## おわりに
いかがでしたか？これでM1 Mac片手にスタバでドヤりながらUSBシリアルデバイスを使ったROS開発ができますね．それでは良いROSライフを！