Teensy4.1でROS2完全に理解した

# はじめに
Teensy4.1でROS2を使うための環境構築を書いていきます．マイコンでROS2を使う場合，micro-ROSとros2arduinoを使うことになると思いますが，その2つの違いについて触れます．

# Teensyduinoのインストール
こちらを読んでね
[teensy4.1完全に理解した](https://qiita.com/NobuHandMaker/items/e73f998759f00e7b25b6)

# ROS2の通信
まず，ROS2の通信方式についてです．
プロトコルにMicro-XRCE-DDSを使用し，基本的に通信方式はTCPまたはUDP通信です．つまり，Wi-FIまたは有線LANということです．他にはSerial通信が使用できます．
USB Serialは有線LANよりも低速となりますので，高速通信が必要な場合は有線LANが必要になるでしょう．

## Teensy4.1のイーサネット
Teensy4.1にはLANポートが使用できます．Arduinoや他のマイコンではイーサネットシールドや[WIZNET](https://www.microchip.com/en-us/development-tool/TWIZ5200)などの追加基板が必要になります．
公式のLANポートは[こちら](https://www.pjrc.com/store/ethernet_kit.html)から購入が可能です．

しかし，輸入ものなので時と場合により高額のときがあります．
イーサネットポート，もっと言うとRJ45 MagJackがあればいいのでもっと安く，早く済むはず！
例えば，Sparkfunが販売している[これ](https://www.sparkfun.com/products/13021)
しかし，LANポートの配線は統一化されていないので，公式のLANポートと同じピンに配線しても通信は出来ません．LANポートはトランスの塊で素人が見ても意味不明．等価回路をつくることも大変です．
公式がこれで，
https://www.pjrc.com/store/ethernet_kit.html
![schematic_ethernet.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/891293/c4f56870-e63f-5f70-dbee-77dd96f908e7.png)
SparkFunのがこれ
[Sparkfun RJ45 MagJackデータシート](https://www.sparkfun.com/datasheets/Prototyping/MagJack.pdf)
![Screenshot from 2021-12-13 22-12-27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/891293/31cddeba-4ad8-8019-5c3f-7f2b4ea50768.png)


**わけわかめですね．** 
と思いきや，Sparkfunの製品で配線している方がいました．神
https://forum.core-electronics.com.au/t/wiring-teensy4-1-to-magjack/8598

LANポートを安く実装したい方は是非参考にしてみて下さい．

## micro-rosとros2arduino
[micro-ros](https://micro.ros.org/)はマイコンでROS2を動かすために開発されているミドルウェアです．[Renesusも力入れています](https://www.renesas.com/jp/ja/application/technologies/robotics/robot-operating-system/micro-ros-solutions)
[ros2arduino](https://github.com/ROBOTIS-GIT/ros2arduino)はArduinoでROS2を動かすためのライブラリです．とはいえ，Arduino IDEが幅広いマイコンをサポートしているため，Arduino以外のマイコンでros2arduinoを動作させることができます．

## 何が違うのか
まず，対応しているROS2のバージョンが違います．
ros2arduinoはROS2 Dashingまでのサポート，Micro-XRCE-DDSはv1.3.0です．
一方，micro-rosは開発が精力的であり，現在の(2021/12/13) ROS2 の最新バージョンGalacticまでサポートしています．

次に，ros2arduinoはArduinoなどのマイコンだけを対象としていますが，micro-rosはその名の通り最小限のROS2のことで位置づけもROS2と同じく「ミドルウェア」であり，「ライブラリ」のros2arduinoとは違います．

## 使いやすさ
安定感は，サポートが終わっているDashingを対象としているros2arduinoでしょう．これ以上の発展はありませんから，変更もありません．一方で，将来性と構築のしやすさはmicro-rosです．Dockerコマンド一つでAgentが入るのが魅力的です．最新バージョンまでサポートしているため，使いやすくなったROS2ライブラリも実装できます．
今回は，モダンなROS2のバージョンまで入るmicro-rosをTeensy4.1にインストールします．

## micro-rosをインストール
基本的に公式のREADMEを見ていけば大丈夫です．
https://github.com/micro-ROS/micro_ros_arduino

### Arduino IDEを使う場合
Arduino環境にmicro-rosのライブラリのZIPをダウンロードするだけです．以下リンク先の「Source code (zip)」をダウンロードして，Arduino IDEの```Sketch -> Include library -> Add .ZIP Library...```を選択し，ダウンロードしたZIPファイルを選択します．
https://github.com/micro-ROS/micro_ros_arduino/releases

出来るならパッチも当てましょう．

```shell
$ export ARDUINO_PATH=[Your Arduino + Teensiduino path]
$ cd $ARDUINO_PATH/hardware/teensy/avr/
$ curl https://raw.githubusercontent.com/micro-ROS/micro_ros_arduino/galactic/extras/patching_boards/platform_teensy.txt > platform.txt
```

### PlatformIOを使う場合
PlatformIOでは，まずはボードをTeensy4.1を選んでプロジェクトを作ります．
その後，platformio.iniファイルに以下のように，lib_depsにmicro-rosのGitHubリポジトリを含めれば大丈夫です．

```ini:platformio.ini
[env:teensy41]
platform = teensy
board = teensy41
framework = arduino
upload_protocol = teensy-cli
lib_deps = https://github.com/micro-ROS/micro_ros_arduino

build_flags =
    -L ./.pio/libdeps/teensy41/micro_ros_arduino/src/cortex-m7/fpv5-sp-d16-hardfp/
    -l microros
```
platformio.iniを書いたあと，以下コマンドでライブラリをプロジェクトにインポートします．

```
$ pio lib install # Install dependencies
```

あとは普通にアップロードすれば大丈夫です．と思いきや，自分の環境ではトピックが受信できませんでした．**要検証**

### micro-ros-agentのインストール
Micro-ROSのAgentをDockerでダウンロードします．

```shell:ros_Agent_install
# Serial micro-ROS Agent
docker run -it --rm -v /dev:/dev --privileged --net=host microros/micro-ros-agent:galactic serial --dev YOUR_BOARD_PORT -v6
```

YOUR_BOAD_PORTはTeensy4.1が接続されているポートを選択します．以下コマンドなどでわかります．

```
$ lsusb
または
$ dmesg
```
だいたいは /dev/ttyACM0 だと思います．


起動すると，Agentが指定したポートを監視し始めます．
![Screenshot from 2021-12-14 00-09-16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/891293/f0388470-bded-8e03-f7b5-e6a22253e124.png)

これで準備はできました．

# テストラン 
試しに動作確認をしてみましょう．
ここでは，Arduino IDEで書き込みを行ないます．``` ファイルー＞スケッチ例ー＞ 互換性なしー＞micro_ros_arduinoー＞micro-ris_pubscriber```を開き，Teensy4.1に書き込みます．
![Screenshot from 2021-12-14 00-10-56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/891293/d51ba8d4-ff1b-1bee-4fa8-aef545c0ecff.png)

次に，Teensy4.1を繋いでいるUSBを一度抜き，再度ラズパイに刺して下さい．すると，コンソール上に信号が来ていることが確認できるはずです．

別に新しくターミナルを開いてROS2も起動してみましょう．下記コマンドを打つとROS2 Galacticが起動します．ホストにインストール済みであればDockerで起動する必要はありません．ちなみに，Dockerの場合は```--net=host```オプションは必須ですので**お忘れずに．**

```shell
$ docker run -it --rm --privileged --net=host osrf/ros:galactic-desktop 
```

ROS2が起動したら以下のコマンドを打ってTeensy4.1から来ているトピックを確認しましょう．
ros2 topic listコマンドを打つと，/micro_ros_arduino_nodeというトピックが来ていると思います．

```shell
$ source /opt/ros/galactic/setup.bash 
$ ros2 topic list
$ ros2 topic echo /micro_ros_arduino_node
```

```
data: 1
data: 2
........
```
と，表示されれば成功です．

**おめでとうございます！Teensy4.1のROS2のノードから送られてくるトピックを読み取ることができました！**
ROS2がTeensy4.1で動かすことができましたので，次はサーボを動かすことにも挑戦しましょう．