Rclex で動く Nerves を作った！

おはこんばんにちは、 [NervesJP](https://nerves-jp.connpass.com/) のポジローです。

他でも発表している内容で恐縮ですが、今日は「Rclex で動く Nerves を作った！」の記事です。

## なぜ動く Nerves を作ったか

動く Nerves を作った動機は、 

- Rclex が Nerves で動くようになったのだから、動くものが作れるはず💡
- Nerves の面白さを伝える展示を考えると、動くものがあったほうが良さそう💡
- 使えそうなものも、どうやらそろってそうだぞ🤔

という思いつきからでした。そして、やってみたらできました🎉🎉🎉

## まずはデモ動画

![roscon2023_trim.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369713/2efadcdc-239e-6e4e-8d25-a2f22b933b5d.gif)
※ 動画 was made by @takasehideki & @Shintaro_Hosoai

高瀬さんが大分こだわって作ってくれました。ので、それに協力した細合さんが大変苦労したそうです。

動画から、カメラの載った二輪のロボットがコントローラから操作できているのが見て取れると思います。

また、画面右ではロボットのステータスである

- モーターへの指示値PWM（と対応する物理値）
  - その簡易グラフィカル表示
- 近接センサの値

が確認できます。右下にはロボットに載っているカメラ映像が見えるようになっているので、ラジコンのカメラを見ているようなちょっと楽しい作りになっています。

## 使っているもの

この動く Nerves で使っているものを紹介します。

### [Raspberry Pi Mouse V3](https://rt-net.jp/products/raspberrypimousev3/)

アールティ社製の左右独立二輪方式の小型移動プラットフォームロボットの [Raspberry Pi Mouse V3](https://rt-net.jp/products/raspberrypimousev3/) です。

<img src="https://rt-net.jp/wp-content/uploads/2020/04/Raspberry-Pi-Mouse.png">

> 教育研究用ロボットにおすすめ

として販売されています。ロボット上部にはラズパイ4が載ります。
※ラズパイ4 以前のラズパイも載るようですが、今は入手性や性能から 4 をデフォルトと考えて良さそうです。

このロボットに関わるソースコードは RT 社の Github で公開されており、どのように制御されているかを学ぶことができました。

https://github.com/rt-net/RaspberryPiMouse

https://github.com/rt-net/raspimouse2

https://github.com/rt-net/raspimouse_ros2_examples

### [Rclex](https://github.com/rclex/rclex)

@takasehideki らが Author の Elixir 製 ROS 2 Client の [Rclex](https://github.com/rclex/rclex) です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369713/5361432d-8e54-5c98-5f15-907f6f6631eb.png)


ROS 2 は `rcl` というC言語実装のライブラリを低レベルな API として提供しており、 各言語の ROS 2 クライアント（C++実装である rclcpp, Python実装である rclpy等）はその `rcl` を介して ROS 2 の機能を利用します。Rclex も同様に NIF を介して `rcl` を叩いています。 

Rclex は 次の 0.10.0 のリリースに向けて開発が進められており、私もコントリビュータとして参加しています。 see. https://github.com/rclex/rclex/tree/0.10.0-dev
Rclex の NIF を書いた際のことは、以下に書いているので興味があれば読んでいただけたら嬉しいです。

https://qiita.com/pojiro/items/bfd915ee583fc6822311

### Phoenix LiveView

ラズパイマウスのステータスをリアルタイムにモニターできるように、マウスの Nerves 上で Phoenix LiveViewを動作させています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369713/63986f46-6dac-f5b1-2699-cb07e383e333.png)

モーターへの指示値や近接センサの値を表示できるようにしています。
インジケーターは、指示値に応じて tailwindcss で色をつけた div の高さと位置を変えることでそれっぽく表現しています。

### [Momo](https://github.com/shiguredo/momo)

時雨堂さんの [Momo](https://github.com/shiguredo/momo) をラジコンカメラとなるよう利用しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369713/48cd7ec0-b767-6e73-7149-e43fe7419382.png)

Momo は、 rpi4 の場合、 Linux に必要なライブラリが入っていれば、リポジトリの Releases にあるバイナリをポン置きで使えるので非常に便利です。
※`nerves_system_rpi4` で使う場合にはライブラリが足りないので、カスタムする必要があります。

### [rpi4_mouse](https://github.com/pojiro/rpi4_mouse)

[rpi4_mouse](https://github.com/pojiro/rpi4_mouse) がお手製の Nerves プロジェクトです。

https://github.com/pojiro/rpi4_mouse

deps で以下を用いています。

- UI 用の [rpi4_mouse_ui](https://github.com/pojiro/rpi4_mouse_ui)
  - Nerves にポンチョで Phoenix をもちこむためのリポジトリです
- カスタムした Nervesシステム [nerves_system_rpi4_mouse](https://github.com/pojiro/nerves_system_rpi4_mouse)
  - Momo 用に必要なライブラリの追加と https://github.com/rt-net/RaspberryPiMouse のカーネルモジュールのビルドをするようにカスタムしています
- デバイス制御用の [raspimouse2_ex](https://github.com/pojiro/raspimouse2_ex) 
  - スーパーバイザツリーの構成が雑なので、参考にしないよう注意です💡

## 構成図

使っているものをどのように組み合わせたのかを表すのが以下の構成図です。
点線を挟んで上段がラズパイマウス側、下段がオペレータ側です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369713/c24d6496-2676-223c-cccc-5e22e561852d.png)

マウスが動くまでの流れは以下です。

1. オペレータ（デモ動画内 @takasehideki）がコントローラを操作する
1. その操作信号を PC で起動している Python ROS 2 ノードが拾い、 ROS 2 メッセージを作りパブリッシュする
1. マウスで起動している Elixir ROS 2 ノードがメッセージをサブスクライブし、`raspimouse2_ex`にErlangメッセージとして投げる
1. `raspimouse2_ex`のモーターを制御する GenServer が Linux のデバイスファイル（`/dev/rtmotor_raw_(l|r)0`）に値を書き込み、モーターが動く

UI の値表示は、各デバイスを制御する GenServer から取得した値を Phoenix.PubSub で 100ms で Phoenix LiveViewに投げています。

## 動くものを Nerves で作るメリット

### Elixir を使えることのメリット

他言語の書き味と比べられないのですが、各デバイスの状態保持・操作を GenServer で書けるのが書きやすいと感じました。例として、モーターの GenServer のコードへのリンクを張っておきます。

https://github.com/pojiro/raspimouse2_ex/blob/main/lib/raspimouse2_ex/devices/motor.ex

また、Phoenix LiveView を使った内部状態の可視化のしやすさがあります。
簡単なUIをさくっと、デバイス制御ロジックを書いているのと同じ言語で書けるのが便利です！

### Nerves を使うことのメリット

Elixir で ROS 2 開発ができる点は我々アルケミストにとって嬉しいのですが、 Nerves で作ることのメリットが他にもあります。

Nerves を使う場合とそうでない場合の違いは以下のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369713/535307f3-b7d4-ab4d-b066-f1fcba1f2510.png)
※ROS 2 は開発・動作環境として Ubuntu を要求します。

OS が Ubuntu から Nerves に変わることにより、以下のメリットが得られます。

- 電源断前のシャットダウン処理が不要になる
  - Nerves は RO（リードオンリー） なファイルシステムで動作するのでシャットダウン処理なしに電断が可能 （対処をしない素の Ubuntu はそれをできません）
- ファームウェアサイズが小さく、SSH転送（`mix upload`）での更新が容易
  - Linuxカーネルとルートファイルシステムの入ったパーティションをまるっと更新できます

私はロボット開発をしたことがありませんが、上記は結構、便利なのではないかなと思います。
このあたりはロボット専門にやられている方の意見を聞いてみたいです。

私がつたない文章で書くよりも、動く系で Elixir Stack のメリットを全開に感じられる動画があります。
Elixir Stack(Phoenix LiveView &Nerves) でPID制御を紹介している以下のミートアップの動画です。大変面白いのでぜひ字幕翻訳もつけて見てみてください👀👀👀

https://www.youtube.com/watch?v=56sSifvyKxA

## まとめ？

Rclex とラズパイマウスを組み合わせることで、動く Nerves が一つ作れました🎉🎉🎉
作ってて思いましたが、動くものって作ってる最中がすごく楽しいですね。他にも作ってみたいと思いました！

### 最後にちょっとだけ宣伝 [Open Source Conference 2024 Osaka](https://event.ospn.jp/osc2024-osaka/) 

[NervesJP](https://nerves-jp.connpass.com/) で [Open Source Conference 2024 Osaka](https://event.ospn.jp/osc2024-osaka/)  に出展します。

https://event.ospn.jp/osc2024-osaka/

日程:2024年1月27日 10:00～18:00（展示は16:00まで）
会場:大阪産業創造館 3F,4F（OSC受付：3F）

**この記事で紹介した動く Nerves の実機展示もしますし、「関数型言語Elixirで組み込みLinux開発ができるNervesの紹介」というタイトルで45分のセミナーもします。**

興味あるよ！という方は、ぜひ足を伸ばしていただけたら嬉しいです！
当日は、@pojiro, @takasehideki, @myasu が会場にいるはずです。ぜひ情報交換しましょう〜！

![NCJP_Logo3_V2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369713/30394d87-a981-8530-9762-a971ed5520a3.png)

### 参考

[Raspberry Pi Mouse を Nerves で動かしてみた](https://speakerdeck.com/pojiro/raspberry-pi-mouse-wo-nerves-dedong-kasitemita)