MATLAB/Simulink Home Editionで”実用的に”ROSのノードをコード生成する

#MATLAB/Simulinkで何ができる

MATLAB/SimulinkのHome Editionを趣味で使用している人は多いかと思います。
以前（１年くらい前）に記事にしましたが、Simulinkの最も有益な使い方はオートコード生成と勝手に思っているのですが、Home EditionだとSimulink CoderやMATLAB Coderなどのコード生成の機能を購入することができません。
しかしながら、RaspberryPiやArduinoなどに関しては特別にMathworksさんがコード生成してバイナリを自動生成するという機能を提供してくれています。
（https://qiita.com/tatsuyai713/items/bb4f13e0c8d3ad49e607）

##Simulinkでモデル生成して実機にインプリメントする
自動車会社の車両運動制御系の開発に携わっている方や、今後そのような業務を行いたいという方も多いと思いますが、実際に家でSimulinkのモデルを作成して実機で動作させてというような勉強を行うことは非常に難しいです。
しかし、MATLAB/SimulinkのHome EditionとRaspberry Piのコード生成機能を組み合わせれば、例えば、ルンバなどのロボット制御にSimulinkを用いてコード生成したもので制御するということも可能になります。
実際に自動車開発でよく用いられるDSpaceのMicroAutoBoxなどのリアルタイムでの車両制御はできないものの、かなり勉強になるかなと思います。
かなりのこだわりの強い方などは、「リアルタイム性ガー」とか言い出すかもしれませんが、そのような人はそもそもEmbeded Coderを買うか、もしくはリアルタイム性が求められる部分は自前でCなどでマイコンに実装してください。

##MATLAB/SimulinkにおけるROS
ではルンバなどのロボットを制御するという際に、いきなり、全ての機能をSimulinkで書こうとすると、ハードウェア通信部分などでかなり苦労することになりますし、SimulinkのHome Editionの制約である1000ブロックにすぐに到達してしまいます。そこで、ROSの出番となります。ROSの詳しい説明は端折りますが、SimulinkからROSノードを複数作成し実行することで、Simulinkの1000ブロック制限や他のROSで作成された機能を使用することもできるため、ターゲットとする機能のみをSimulinkでモデルを作成し、ROSノードを生成することで、手軽にSimulinkを用いた実機へのインプリメンテーションを体験することができます。
MATLAB/SimulinkはROSへの対応に非常に積極的で、ROS2への対応も進めています。しかしながら、ROSのバージョンアップなどには追い付けていない現実があります。
特にRaspberryPi上でROSノードを生成する機能については、安定して動作するのはMATLAB R2019aとなっており、それ以降のバージョンではコード生成機能が使用できないなどのバグ（わざと？）があります。また、細々としたバグやかなり分かりづらい操作が必要になるなど、設定にものすごく苦労するので、今回その手順をまとめたいと思います。

##Simulinkで作成したモデルをROSノードにする手順
MATLAB/Simulink R2019aとRaspberryPiの拡張機能をインストールし、以下のような条件でROSノード作成の手順をまとめたいと思います。

- ハードウェア
    - Raspberry Pi 4B　（Ubuntu 20.04 LTS aarch64）
    - Ubuntu 20.04 LTS (x86_64) のPC（WindowsやmacOSでもできます）
- 作るもの
    - 既存のROSノードとTopic通信してデータを取得し、ある計算処理を行って、別のROSノードにTopic通信でデータを受け渡す

あえて、Mathworksが正式にサポートしていない方法をとっていますが、今からROSの環境を整える場合は、Ubuntu 20.04でしょうし、Raspberry Piも4Bがメジャーですし、RaspbeanよりUbuntuの方がaptコマンドでROSがインストールできるので、これで進めます。

###Raspberry Pi 4Bの準備
これはさすがに端折りますが、基本的には、Raspbery Pi 4B用のUbuntu 20.04のイメージをSDカードに書き込んで、設定後Desktop環境のインストールとROSのインストールを行うだけです。
Ubuntuを使う分には、以下のROSのインストールの手順に従えば終わりです。
http://wiki.ros.org/noetic/Installation/Ubuntu

###PCの環境の準備
PCはMATLAB/Simulink R2019aがインストールできる環境であれば基本は大丈夫です。
というのも、MATLABにはrosinit()という関数で、roscoreを立ち上げることができるので、WindowsでもROS環境を意外と簡単に作ることができます。今回は、Raspberry Piへのインプリメンテーションなので、roscoreはRaspbnerry Piで立ち上げるので、特に気にする必要はありませんが・・・

###今回の例題
今回の例題は、せっかくSimulinkでモデルを作成して、実機で動作させるということもありますので、CANで通信して、データを取得して、取得したデータに何らかの演算をして、それを別のCAN IDで送信するということをやってみたいと思います。ただし、CANの通信部分については、Simulinkで記述することも不可能ではありませんが、Simulinkの得意とするところではありませんので、CANの通信部分については別途、以下のROSパッケージを使用するとします。
https://github.com/tatsuyai713/ros_socket_can_driver

####ROS TopicとROS Paramの使い方
ROSの通信でよく使われるものとして、トピック、サービス、パラメータがあります。サービスについては、Simulinkなど制御系で使用するには、サーバーに問い合わせてレスポンスが返ってくるまでブロッキングしてしまうので、色々と調子が悪いです。ですので今回は、トピック通信とパラメータについて取り上げます。

####ROS ParamをSimulinkで使用する
ROS ParamをROSで使用すされた方はわかると思いますが、通常よくやるやり方としては、コンストラクタなど、ROSノード起動時に一度だけLaunchファイルなどParamを読み込んでくるというような使い方をする方が多いと思います。しかしながら、Simulinkにおいて、ブロックを配置するとどうしても、Simulinkで設定した周期でそのブロックが実行されてしまいます。処理周期ごとに毎回パラメータを取得することは問題ないように思われるかたも多いと思いますし、実際動作自体には問題は起こりません。
しかしながら、このROSノードを実行して、topやhtopでCPU使用率を確認すると、ROS Masterに異常な負荷がかかっていることがわかります。理由は言わずもがな、毎周期ROS Masterにパラメータの問い合わせが発生するため、ROS Masterの負荷が高くなっているというのが原因です。
とはいえ、ROS Paramは使いたいという方が非常に多いと思いますので、Simulinkで使用するコツとしては、下の図のようにSample TimeをInfに設定してしまいます。すると、Simulinkは初回実行時のみこのブロックを実行し、その後は問い合わせが発生しません。しかし、rosparam setなどでモデルの実行中にパラメータの変更をしてもそれは反映されないので、適宜Infを現実的な周期に設定することで、rosmasterへの問い合わせの負荷を最小限にしながらパラメータの更新が出来ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/e1cfac1f-e927-d69e-ef76-2de3430d85f7.png)


####ROS Topicを上手に使いこなす
ROS Topicは、通常ROSノードを作成する場合、Topicの受信によりコールバック関数が呼ばれ、その中で処理を行うのが一般的です。しかしながら、一部の例外をのぞき、Simulinkでコールバックによる割り込み処理を実行することが難しく、SimulinkでROSのトピック受信ブロックにもその機能は実装されていません。よって、基本的にその時にPublishされた最新のデータを取得して、処理の周期は、Simulinkで決めた周期に従って処理を進めることになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/ee6bc031-3e2c-2518-867b-a4d92b60c7ee.png)

すると、ここで、Simulinkで制御系を組んだりする場合に大きな問題にぶち当たります。
それは、Topicがやってくるかどうかに関わらず、このSimulinkのROSノードは実行を続けてしまうため、何かの不具合で送信元のROSノードが死んでいるにも関わらず、処理が継続し、その結果想定しない制御指示値などが出力されてしまう懸念があります。
その場合には、以下のようなブロックを作成しておくと非常に便利です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/e7357ac6-aa68-4f05-6acd-a4eac21d8fb5.png)

ROSのSubscribeのブロックにはデータを受信すると、1を出力するポートがあります。こちらを使用して、前回受信してから一定時間新しいデータを受信しない場合エラーを出力するというブロックになります。
こちらを各Subscriber毎に設置することで、もしなんらかの原因でROSトピックのデータが更新されない場合でも、正常にフェイル動作が可能となります。

####ROSのカスタムメッセージを使用する
基本的なROSを用いたSimulink上での開発というのは、これまでのROS ParamとROS Topicを用いたもので十分可能です。しかし、一般的にROSのTopicを扱うときに殆どの方が自分仕様のmsgファイルを用意して、それを使ってTopic通信することが多いと思います。
基本的にSimulinkでも一般的に用いられる、std_msgsやgeometry_msgsなどに用意されるメッセージはあらかじめ用意されていますが、オレオmsgに対応しないとなると、他に作成していたROSノードと通信できないなどのめんどくさい問題が発生してしまいます。

そこで、Simulinkではカスタムメッセージを用いることができる拡張機能が提供されています。なおR2020b以降においてはこの機能がROS Toolboxに取り込まれたようです。

ではカスタムメッセージを使用する方法について説明していきたいと思います。一点注意点としては、Ubuntu上でのMATLAB/Simulinkを用いて、開発する場合のみMATLABのホームページに載っている方法では上手く動作しないので、そちらについてもやり方を書いていきたいと思います。

#####カスタムメッセージの拡張機能をインストールする
MATLABのカスタムメッセージ機能を使うためには、先ほど書いた通りアドオンをインストールする必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/21721ea6-9c53-2b0d-555f-a3757caa1a39.png)

やり方は非常に簡単で、ROSという名前で検索して、ROS Toolbox Interface for ROS Custom Messagesというのを選択してインストールするだけです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/28e95ecf-23d4-8815-e97d-24505bd4644e.png)

#####カスタムメッセージを含むROSパッケージの準備

続いてMATLABがインストールされているPCにカスタムメッセージが含まれているROSパッケージを持ってきます。このとき、特段catkin_wsだとか、ROSのワークスペース的なルールは存在しません。ただし、このフォルダは今後MATLAB起動毎に読み込みにいく必要があるため、MATLABのPATHに追加することになりますので、わかりやすいところ（Document以下のMATLABフォルダの中など）におくことをお勧めします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/b06788f0-dddb-bc0c-13ad-617ec000d3ac.png)

ということで、先ほど例で使用するCAN通信のROSパッケージをgit cloneでとってきました。

#####カスタムメッセージをMATLABに登録する

続いて、MATLABのコンソールで、以下のコマンドを実行します。

```console
rosgenmsg(".")
```

ただし、Ubuntuを使用している方は、ここで大きな問題が発生します。通常MATLABをsudo権限で実行することはないのですが、このあとここで作成したカスタムメッセージのフォルダのパスを追加するなどの作業に管理者権限が必要となってしまします。ですので、ここでUbuntuを使っている方は、Terminalから sudo matlabで管理者権限でMATLABを起動し直してから実行するようにしてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/f18a9fba-2011-35d1-5be4-4a786b5f3942.png)

すると、このようにカレントフォルダに存在するROSパッケージを全て調査して、カスタムメッセージが存在する場合は自動でカスタムメッセージ用のjarファイルを作成してくれます。matlab_genというフォルダがそれになりますので、これは削除しないようにしてください。
ここで、この表示に従って、javaclasspath.txtを編集し、パスの追加コマンドを実行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/0e9ebd63-eca3-001a-696d-fe04af8e9cdb.png)

指示に従って、MATLABを再起動します。この際、Ubuntuの方は、sudo権限で実行する必要はなくなりますので、これ以降は通常の権限で実行しても構いません。

ここで、重要な注意点ですが、今回作成したカスタムメッセージを使用してSimulinkモデルを作成した場合、そのモデルを誰かに渡す場合など、この操作と同じ操作を実行しておかないと、Simulinkモデルを編集したとしてもエラーが出て保存することができません。これは、どうやらSimulinkがモデルを保存する際に、ROSのブロックのメッセージを確認するようで、不正な値（知らないカスタムメッセージ）が存在するとエラーになってしまうようです。色々回避策は探したのですが、ないようですので、こればかりはカスタムメッセージを使用したモデルのやりとりを行う時は必ず、ROSパッケージもセットでかつ、同じ作業をしてもらうようにしてください。


####ROS Topic受信のモデルを作成する
さて、これで一通り準備が完了しましたので、実際にSimulinkモデルを作っていきます。まずは、ROS Topicを受信して、受信した内容を解析するモデルを作成していきます。

![スクリーンショット 2021-04-10 19.23.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/4a80def3-b073-e0d7-befb-c76b100d9b4a.png)

ということで、いきなり完成図になります。
先ほど書きましてROSトピックが来なくなったときにきちんと終了するようにSTOPのノードを繋げています。
ROSのカスタムメッセージなどで定義している配列に関しては、Simulinkではたとえ数が少なくても128行のベクトルとして扱われるようです。これは後述する送信の時にハマりやすいポイントですので、覚えておきましょう。
設定としては、時間進行をFixedStepDiscreteにすることをお勧めします。

また、Simulinkに慣れていない人は馴染みがないかもしれませんが、Simulinkには複数の信号を束ねて一つの信号として、やりとりができるBUSという仕組みが用意されています。ROSのメッセージはBUSとして扱われますので、SubscribeのブロックのMsgの出力はBUSとなります。
BUSから目的の信号を取り出すブロックがSimulinkには用意されていますので、これを用いて、必要なデータを取得していきます。

注意点としては、カスタムメッセージの型のまま取り出ししかできないため、CANのようなバイト列のデータを意味のある数値に変えていくのは少し手間がかかります。（ビットシフトと型変換を駆使することになります）

###Simulink上でROSノードを実行する

よく考えたら、Simulink上でROSを実行する方法について書いていませんでしたので、記載していきたいと思います。
ROSの詳しい説明は端折りますが、ROS1ですので、ROSを動作させるネットワーク上に一つのroscoreを立ち上げておく必要があります。

とりあえずROSを使用したSimulinkモデルを実行すると以下のようなエラーが出ると思います。
エラーが出る前に設定しておけば問題ないのですが、この設定にいく手順がバージョンによって違ったりして、わかりにくいので、ここでは一度実行させてわざとエラーを出させています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/4a0e72e4-1fa6-c6d1-c043-bc185c65a2b0.png)

エラーに出ている開くのボタンを押すと以下のROSのネットワーク設定の画面が現れます。
ここで、ROS Masterを指定する必要がありますが、こちらはroscoreを実行したHostのIPアドレスを指定します。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/c778a9b0-284e-a755-4eb4-f4cd29c8ace9.png)


私の場合は、大体他のターミナル上などでroscoreを実行しておきますが、MATLABには実はROS Masterが取り込まれており、以下のコマンドをMATLAB上で実行することで、MATLABでROS Masterを立ち上げることも出来ます。

```console
> rosinit
```

止めるときは

```console
> rosshutdown
```

roscoreを立ち上げましたら、先ほどの設定画面でTestというボタンをクリックするとROS Masterとの通信が成立するかの確認をしてくれます。
ちなみに、Defaultを選んでいると、localhostにROS Masterがいると判断します。


これで、Simulink上で、ROSを使用したモデルの実行が可能となりました。
実際に実行してみると、問題なく進むことがわかりと思います。
ただし、MATLABの某ツールボックスを入れていないと、リアルタイムでのシミュレーションができないため、残念ながらものすごいスピードで時間が経過していきます。（Simulinkはシミュレーションの環境なので、実時間では動作しません）

このことからわかるように、Simulink上で時刻を扱う時はROS Timeを使用するようにしましょう。ROS Timeであれば、
ROS時間を使うので、Simulink上で爆速で動作していても問題なく処理が可能です。
また、Simulinkでのシミュレーション時間はInfに設定しておけば、ユーザー操作で止めるまでずっと動き続けるのでお勧めです。

###ROS Topicを受信して計算処理の後に別のROS Topicを出力するモデルを作成する

さて、ここまでで、カスタムROSメッセージをSimulinkで受けて、それを解析することはできるようになりました。続いて、こちらで計算した結果をROSのネットワークに戻す処理をしていきます。

今回はこのようなモデルを作成しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/17b035a9-fb08-f836-451b-3c698232440d.png)

受信の部分と送信の部分が分離しているので、結局意味はあまりないのですが、そこはご愛嬌ということで・・・

送信の箇所がかなり複雑になっていることがわかると思いますが、一つ一つ説明していきたいと思います。

今回使用したCANのカスタムメッセージの定義は以下のとおりとなっています。

```
std_msgs/Header      header
string               can_msg_name
uint8                can_channel
uint16               can_id
uint8                can_dlc
uint8[]              can_data
```

1. 送信するROSメッセージのBlankメッセージを用意して、そのメッセージが内包されているBUSの中身を編集する

Simulinkは何もないところから信号を生成するブロックは用意されていますが、ROSに対してはそのようなブロックを用意していない、というかそもそもカスタムメッセージを扱う以上出力ブロックを用意するのは現実的ではないからか、Blankメッセージを用意して、それを書き換えていくことになります。なので、ROSのBlank Messageで出力したいMsgを選択して、BUS Assignmentを用いて、BUSに含めれるデータを更新します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/d9d520b0-36d2-9091-72b9-2d7257e93b3f.png)

このように、Headerのような他のstd_msgsのMsgが含まれる場合も個別に指定できるので、非常に便利です。

2. ROS Msgで配列を送信したい場合のデータの用意

今回のCANのカスタムメッセージで非常に面倒になるのが、CANDataのバイト配列を入れていくところになります。
この場合には、Byte Packというブロックを使用すると非常に楽に実装することができ、たとえばint16のようなデータをuint8のvectorに変換してくれるという組み込み系には必須なブロックとなっています。
ただここで、先ほども書きましたが、ROSのMsgの配列は128個で決め打ちになっているので、たとえば2バイトのデータを送りたいと思っても、配列は128で用意しないといけません。そこで、いちいちめんどくさいですが、今回の場合は、残りの126要素を0で埋めてデータを作成しています。

3. Time Stampを使用する場合は、ROSのCurrent Timeを使う

これは先ほども書きましたが、Simulinkのシミュレーションで扱う時刻は、Simulationでの時刻になります。ですので、これをそのままROSの世界の時刻とは同期できません。そこで、ROSのToolboxにはCurrent Timeというブロックが用意されているので、それを使用します。

最後に、DLCなどのデータを入力して、更新したBUSのデータをPublishのブロックに入力して、出力したいTopic名をコンフィグで設定すれば完成です。

###作成したモデルをRaspberry Pi上で実行する

ここまででSimulinkを用いてROSとの通信を行いながらSimulationする方法を説明してきました。しかし、あくまでSimulinkでのシミュレーションになるので、大きなモデルともなると速度が低下して、あらかじめ決めたシミュレーションステップ時間に間に合わない場合や、逆にTopicをPublishする場合など、10msec周期でPublishしたいと思っても、このままでは時刻を守った出力というのは非常に難しくなります。
そもそも実機での運用の際は、ROSノードにして実機に搭載される環境にデプロイしたいということになります。今回は、特にコード生成に必要なSimulink Coderなどのライセンスがなくても、コード生成を行いROSノードとして実機にデプロイする方法を紹介したいと思います。

MATLABでは、個人の学習などの目的のために、ArduinoやRaspberry Piなどのプロトタイピング環境に、高価なCoder系のToolboxがなくてもコード生成が使用できるようにしてくれています。
今回は、ROSでのコード生成になるので、ROSに対応したコード生成可能なプラットフォームはRaspberry Piのみですので、Raspberry Piを用いた方法で行います。

####Raspberry Piのアドオンをインストールする

Raspberry Pi用のアドオンはハードウェアサポートパッケージを検索することで出てきます。

Raspberry Piに関するものはMATLAB Support PackageとSimulink Support Packageの２つになりますので、これを2つともインストールしましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/e999b5c2-2a30-427e-628a-215053209ce6.png)

インストールが完了すると、設定を行うか？という画面が出てきますが、これはスルーして後で設定します。

####Raspberry Piを準備する

ここで、ROSを実行するためのRaspberry Piを準備します。いつも皆さんはx86のPCにUbuntuをインストールしてROSを実行していると思います。ただ残念なことに、MATLAB先生は（公式には）Rasbeanしか対応していません。ご丁寧にRaspberry Piの設定を行うところで、RaspbianのSDカードを作成してくれるような案内が出てきますが、何が入っているかわかったものではないので、もちろん使用しません。
ここでは、Raspberry Pi 4にUbuntu 20.04 LTSをインストールしてROSまでインストールが完了した環境を例に進めていきます。Raspberry Pi 4にUbuntuとROSを入れる方法は多くの方が書かれていたりするので、すっ飛ばします。。。

さて、Raspberry Piの準備が終わりましたら、MATLABから使えるようにしていきます。
ここにも数々の罠がありますので、順に説明していきます。

Raspberry Piの設定はアドオンをインストールした際に最後に出てきましたが、先ほどスキップしたので、設定画面を出さないといけません。これが非常にわかりずらいのですが、アドオンの管理のところから該当のSimulink Support Package for Raspberry Pi Hardwareの行の右に歯車のマークがありますが、こちらをクリックすることで、設定画面を出すことができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/56bed33f-548c-fd05-8afe-dc4f0b7f0be6.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/e6815bce-e8df-4a2a-4a59-f9a86d331368.png)

ここで、いきなりつまづくのがRaspberry Pi 4が選択肢にありません。。。
というのも、R2019aを使用していていて、最新のRaspbeey Piのサポートパッケージをインストールしたとしても、新しいRaspberry Pi4の機能が有効にならないという極悪な仕様になっています。ただ、MATLABのバージョンをあげてしまうと、今度は逆にMathworksのバグで、Raspberry PiでROSのコード生成ができなくなってしまっています。ですので、ここはRaspberry Pi 3Bとして先に進めていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/176c6395-0f05-9162-38ad-8bc59fe59539.png)

こちらが先ほど書いていた、Mathworksが用意したRaspbianを使うように言ってますが、下の方を選びましょう。

ここからの手順は前に書いたこちらの記事と同じ手順で進めていきます。
https://qiita.com/tatsuyai713/items/4f639a360bdeadcc32c3


続いて、MATLABからRaspberry Piにアクセスできるように接続の確認画面が出てきます。
この画面を見ていただくと、わかるのですが、MATLABはこの後sudoで色々勝手にインストールを始めたりしますので、passwordless sudoの設定を行なっておく必要があります。

やり方は、

```console
$ sudo visudo
```

でsudoの設定のファイルが開けますので、こちらを編集します。
最後の行辺りに

```console
<user名> ALL=(ALL:ALL) NOPASSWD:ALL
```

と記載すればOKです。終了のやり方などはnanoと同じです。（visudoとかいうのに何故かnano）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/75aa9f1f-6e59-3717-7c18-5e03ed7c9ef1.png)

その後、MATLABのセットアップからTest Connectionを実行して、上の図のように全てOKになれば大丈夫です。

さらに今回はRaspbianではなくUbuntuを使用しているため、config.txtやcmdline.txtの保存場所が異なることから、後でエラーになってしまうので、以下のコマンドでシンボリックリンクを張っておきます。

```console
$ sudo ln -s /boot/firmware/config.txt /boot/config.txt
$ sudo ln -s /boot/firmware/cmdline.txt /boot/cmdline.txt
```

UbuntuのイメージにはRaspberry Piのfirmwareに含まれるDynamic Link Libraryがないので、以下の通り取得しておきます。

```console
$ wget https://github.com/raspberrypi/firmware/archive/refs/tags/1.20210303.tar.gz
$ tar xvf ./1.20210303.tar.gz
$ cd firmware-1.20210303/
$ sudo cp -rf ./opt/vc /opt/
$ sudo vi /etc/ld.so.conf
```

以下を追加

```
/opt/vc/lib/
```

この後再起動してください。
再起動後ldconfigしておきます。

```console
$ sudo ldconfig /opt/vc/lib/libmmal.so
```

エラーが出なければOKです。

続いて、/dev/spidev0.xのパーミッション設定を修正する必要があります。が、そもそもグループにspiがないので追加からやります。

```console
$ sudo addgroup spi
$ sudo gpasswd -a <ユーザー名> spi
$ sudo chgrp spi /dev/spidev0.0
$ sudo chgrp spi /dev/spidev0.1
$ sudo vi /etc/udev/rules.d/50-spi.rules
```

で以下を追加

```
SUBSYSTEM=="spidev", GROUP="spi", MODE="0660"
```

さらに何故かMATLABはpiというuserじゃないといけないそうで、
piというユーザーに色々設定しようとしてきますので、とりあえずアカウントだけ一時的に作っておきます。

```console
$ sudo adduser pi
```

あとは適当に入力してください。

事前準備はこれでOKです。

続いて、進むと以下の画面が出てきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/3a591e15-7bf0-81ba-c890-6f677e8ffa9f.png)

これはこれからこれらのパッケージが自動でMATLABによりインストールすることを表しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/d61d4b16-3c6d-ef87-b770-4b47ea6d2a7c.png)

ここでインストールをクリックすると開始します。
ライブラリをコンパイルし始めたりするようで、それなりに時間がかかりますが気長に待ちましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/e1f9d3be-c416-c909-f418-73e4e58afaea.png)

ここに出てくる３つはインストールできなかったということですが、一応次に進めるので進んでしまいます。
GPIOをいじりたい人は、別途これらを入れるようにしてください。

とりあえず頑張れば以下の手順で入れることはできますが、正しく動くかなどは確かめていないので、自己責任でお願いします。

sense-hat

```console
$ sudo apt install python3-pip
$ sudo pip3 install sense-hat
```

userland

```console
$ wget https://gist.githubusercontent.com/satmandu/c462ab301cbe09bd6e7cf4db7f626727/raw/1b5fe9faa027841713941c65f53efb55af537640/build_arm64_rpi_userland.sh
$ chmod +x ./build_arm64_rpi_userland.sh
$ ./build_arm64_rpi_userland.sh
$ cd workdir/output
$ sudo apt install gcc-10-cross-base libc6-armhf-cross libstdc++6-armhf-cross libgcc1-armhf-cross
$ sudo dpkg -i ./rpiuserland_3fd8527_arm64.deb
```

pigpio

```console
$ sudo pip3 install pigpio
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/ced2a31e-3627-4f94-52c1-984eabcecbc4.png)

続いて上のような設定画面が出てきますが、全部Enableに変更しておきましょう。
いわゆるconfig.txtを書き加えてくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/4aa993aa-950b-f964-1aed-80639eb7d8c7.png)


続いて、SimulinikからRaspberry Piに送り込むためのROS用のワークスペースを作成しておきます。

```console
$ mkdir -p catkin_ws/src
$ cd catkin_ws/
$ catkin_init_workspace ./src
$ catkin_make
```

Raspberry Pi上で自分のアカウントを作成して使用したい時は、以下の通りきちんとグループに参加させておきましょう。（全部はいらないですが。。。）
あとセキュリティのため、先ほど作成したpiのアカウントとubuntuアカウントは削除しておいた方が良いですね。

```console
$ sudo gpasswd -a <ユーザー名> adm 
$ sudo gpasswd -a <ユーザー名> dialout 
$ sudo gpasswd -a <ユーザー名> cdrom 
$ sudo gpasswd -a <ユーザー名> floppy
$ sudo gpasswd -a <ユーザー名> sudo 
$ sudo gpasswd -a <ユーザー名> audio 
$ sudo gpasswd -a <ユーザー名> video 
$ sudo gpasswd -a <ユーザー名> plugdev 
$ sudo gpasswd -a <ユーザー名> netdev 
$ sudo gpasswd -a <ユーザー名> lxd 
$ sudo deluser pi
$ sudo deluser ubuntu
```

これでやっとこさRaspberry Piの準備は完了です。


####SimulinkからROSノードをRaspberry Piにデプロイする

ここで、やっと今まで作成したSimulinkモデルをRaspberry Pi実機にデプロイする環境が整いました。
まずはモデルコンフィグを設定していきますので、Simulinkの歯車マークをクリックして、左のメニューからハードウェア実行を選択してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/2b433df5-b345-83dd-2e84-0f49e4413183.png)

ここで、ハードウェアボードにRaspberry Pi - Robot Operating System (ROS)という項目がいるので、そちらを選択します。

次に下にあるデバイスの詳細をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/afe9fa08-54ca-7731-d986-d89b0037cd0d.png)

これだけをみて、これではダメだと気づいた方は相当すごい人ですが、普通の人は気がつきません。
これは以前にも記事にしたのですが、そもそもMATLABのRaspberry Piに拡張機能がそもそもarmhfつまり32bitしか対応していないのです。
ということで、無理矢理対応させていきましょう。

まず、このSimulinkモデルの拡張子をzipにしてしまいます。
そして解凍してしまうと以下のような構成になっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/e7ecf8ac-9adb-351b-a83f-ee00368cba72.png)

そして、以下のように該当箇所を書き換えてしまいます。

```console
$ vi simulink/configSet0.xml
```

```
<P Name="ProdBitPerLong">32</P>
これを
<P Name="ProdBitPerLong">64</P>
こう
```

そして、何事もなかったようにzip圧縮もしくは、変更したファイルだけ中身を書き換えてしまうと、
64bitに対応させることができます。

続いて、Target hardware resourcesの内容を設定していきます。
上のTask PriorityはLinuxに詳しい人は自分でいじっておきましょう。
Package Informationは、見ての通りライセンスに関する記述をしていきます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/ca9daee4-a8d6-ccf0-2c99-dc57f1313c7f.png)

次にRaspberry Piにデプロイする時に必要となる、Board Parametersを設定していきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/95bdff75-506f-c5e9-3be4-f74c29a86349.png)

パスワードが平文なのが納得いかないですが、まあMathworksなので仕方ないです。

最後にBuild optionsですが、こちらのBuild actionは標準でBuild and runになっているますが、実行するのは手動でいきたいところですので、Build and loadに変更しておきましょう。

なお、このCatkin workspace内に、Simulinkからデプロイされるのですが、Simulinkから自動でcatkin_makeコマンドが実行されるため、以下の２点に注意しましょう。

1. カスタムメッセージを使用した場合は、カスタムメッセージのパッケージも同じフォルダに配置しておく。
2. catkin_makeコマンドが実行されるため、catkin buildでビルドをしている人は、buildとdevelフォルダを削除しておく。

 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/d0e95e79-150e-91e0-409c-395ee300b02d.png)

これで設定は一通り完了となります。

右上にある、ハードウェアに展開というボタンをクリックすると、自動でビルドが開始され、実機にデプロイまで自動で完了します。

ただ注意点としては、このハードウェアに展開という処理を行うためにもrosocreが存在しないといけないので、
初めの方で設定したIPのPC上なりで、roscoreを立ち上げておきましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/031a3699-713b-7dc4-783a-f02e33e8638c.png)

下の診断の表示というところをクリックすることで、進捗が見えますが、これをみていくとわかるように、PC上でソースコード生成を行なったあと、それをtarballにしてscpで転送、Raspberry Pi上で展開し、catkin_makeコマンドを実行します。
そのあと、（Mathworksさんはケチなので）コード生成に使用したtarballや解凍したソースコード含めて、コード生成に関わる部分は全て削除されます。
つまり、一度Simuklinkでコード生成を行なって実機にデプロイしたあと、実機で手動でcatkin_makeを実行しても、残念ながらSimulinkが生成したコードは消されているため、ビルドエラーになってしまいます。
ですので、ここで生成したバイナリは保管しておいて、実際に開発するワークスペースにコピーして使用するのが良いかと思います。
また、このSimulinkで自動生成されたROSのバイナリはバイナリしかなく残念ながらlaunchファイルなどは存在しないので、launch専用のROSパッケージを作成して、実行するようにしないといけません。（バイナリを実行ファイルとして、実行することはできますが、paramの設定など他のROSノードと連携もできないので、Launchは別にきちんと用意することをお勧めします。）

##終わりに
最後の方は、かなり駆け足になってしまいましたが、この手順にしたがって進めていくだけで、Simulinkで作成した制御系のアルゴリズムなども簡単にROSノードとして、実装することができます。またMicromouseの大会に出たい人用の１年限定のライセンスなどでは、Simulink CoderやEmbeded Coderも使えるので、それを使えば、このような煩わしいことをしなくても、実機にデプロイするためのROSノードを作成することもできます。

さらに高度の使い方としては、画像処理なども実機で動作させられるといった利点もあるので、これをうまく活用していただいて、Simulinkを使いこなしてROS対応ロボットの開発効率の向上に貢献できればと思います。