TOPPERS/単体ロボットシミュレータ教育演習

#サマリ
TOPPERS箱庭WGでは，[単体ロボットシミュレータ](https://github.com/toppers/hakoniwa-single_robot) をOSSとして一般公開しています．

本記事では，単体ロボットシミュレータ上でのロボット制御するための方法を演習を通して学んでいきたいと思います．

ちなみに，シミュレータを使うと何がうれしいか？を４つ挙げるとするとこんな感じです．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244147/1c867a0a-d4cf-3345-bea1-850b4a60f9bc.png)

#本演習を通して学べること

1. 単体ロボットシミュレーション環境を利用できるようになる
2. EV3RT API を利用してロボット操作ができるようになる
3. 単体ロボットシミュレーション演習課題をクリアできるようになる

#単体ロボットシミュレータのインストール
単体ロボットシミュレータのインストール手順はTOPPERS/箱庭のgithub上で公開しておりますので，こちらを参照ください．

https://github.com/toppers/hakoniwa-single_robot/blob/main/README.md

不明点とか要望ありましたら，こちらでディスカッションさせていただけますと幸いです．

https://github.com/toppers/hakoniwa/discussions/categories/q-a

#単体ロボットシミュレータの構造
単体ロボットシミュレータは，デスクトップパソコン上で，Unity上のロボット(1個)と仮想マイコンを連携させたシミュレーションを実現しています(下図)．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244147/44196d93-7eea-7c15-3dd3-cc6fe61fcda2.png)

主な構成要素は次の通りです．

- ロボット本体
  - モータ/センサ等
- ロボットを制御するマイコン
  - RTOSおよびロボット制御プログラム(C/C++)が動きます
- 外部環境
  - 走行コース/障害物等

#ロボット制御プログラムの編集・ビルド方法を学ぶ
まずは，ロボット制御プログラムの環境を作りましょう．
ロボット制御プログラムは基本的にはC言語で行います．プログラム編集エディタは何でもよいですが，ここではVSCodeで説明していきたいと思います．

##Vscodeを起動する
VSCodeをインストールしていただき，起動してください．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244147/7ea2c50a-d3c8-8283-b423-020c89a874d3.png)

##開発用フォルダ追加/ターミナル設定
[ファイル]→`フォルダを開く`をクリックし開発用フォルダを追加します．
開発用フォルダは今回の場合は，以下としてください．

`{単体ロボットシミュレータのインストールフォルダ}/hakoniwa-single_robot/sdk/workspace/base_practice_1`


##プログラム編集画面を開く
エクスプローラビュー上に `app.c` ファイルが見えると思いますので，ダブルクリックしましょう．成功するとこうなります．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244147/64ec4ff7-08c4-0309-2ddb-91877b39070e.png)

なお，このファイルが本演習で利用するロボット制御演習プログラム本体です．

##ターミナルを開く
プログラムのビルドやシミュレーション実行は，ターミナル上で行います．WSL2を単独で起動してもよいですが，今回はVSCode上でやってみましょう．

[ターミナル]→`新しいターミナル`をクリックしてください．
画面下にターミナルが開きます．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244147/64b28356-7846-e7dc-3a8b-3879d5f09d47.png)

この状態でWSL2に切り替えるために，ターミナル上で wsl を実行してください．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244147/c1fd3ebf-8f76-3d01-e1b6-e06fd438aabc.png)

成功後，作業用ディレクトリを`hakoniwa-single-robot`に切り替えます．

```bash
$ cd ../../../
```

また，単体ロボットシミュレータでは，ターミナルを３個使いますので，以下のように３個用意しておくと便利です．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244147/5f17c317-81b3-b705-7559-2c189eb72f7c.png)

##ビルド方法
プログラムのビルド方法は，先ほどのターミナルを利用して，以下の手順に従って実施できます．

https://github.com/toppers/hakoniwa-single_robot#%E3%82%B7%E3%83%9F%E3%83%A5%E3%83%AC%E3%83%BC%E3%82%BF%E3%81%AE%E5%AE%9F%E8%A1%8C%E6%89%8B%E9%A0%86

以下，本環境でビルドするまでの操作内容です．

### ターミナルAでの操作
```bash
$ sudo service docker start
$ bash run-proxy.bash base_practice_1
```

### ターミナルBでの操作
```bash
$ bash build-app.bash clean
$ bash build-app.bash base_practice_1
```

#シミュレーション実行方法を学ぶ
シミュレーション実行するには，ターミナルCで以下のコマンドを実行します．

```bash
$ bash start-unity.bash single-robot
```

成功すると，以下のようにUnity画面が起動しますので，画面左上の`開始`ボタンをクリックするとロボットが動き出します．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244147/3c9f82c0-705a-8bcc-a392-82828d0a899c.png)

なお，以下のようなログが出力されて失敗する場合は，Unityアプリがダウンロードされていません．

```
start-unity.bash: line 31: ./single-robot.exe: No such file or directory
```

この場合は，以下のコマンドでUnityアプリをダウンロードすることで解決できます．

```bash
$ bash unity/download.bash single-robot  hackev-v1.0.0/WindowsBinary.zip
```

#ロボットを操作して，走る・曲がる・止まるを実現する

##プログラム構成説明
app.c に main_task() という関数があります．これが，本演習でのプログラム制御処理関数となります．

main_task()の最初のコードブロックでは，各種センサ/アクチュエータのポート設定が行われています．その後に，while ループ分があり，この中で制御プログラムを書きます．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244147/ef3eee4a-a93c-f507-b92d-4677f748f8be.png)

本演習では，制御プログラムは 100msec周期で駆動するように設定されています(以下のコード)．

```C
tslp_tsk(100000); /* 100msec */
```

また，画面上で分かる通り，`#if 0` となっており，デフォルトでは，`else`側の`do_practice_2()`という関数が実行されるようになっています．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244147/d2b652f6-d658-51fb-b891-a24731c9a88f.png)

本演習中は，以下のように，`#if 1`として，このコードブロック部分を編集してください．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244147/93aa12d9-a5eb-3afb-8e27-e95f33cfa1fa.png)

なお，上記コードをビルドしてシミュレーションするとロボットの動きが変わると思いますので，ぜひ試してみてください(詳細はこれから説明していきます)．

##ロボット制御用API
本ロボットをC言語で制御するためのAPIがありますので，API仕様を把握したい場合は以下をご参照ください．

https://www.toppers.jp/ev3pf/EV3RT_C_API_Reference/index.html

本演習では，上記APIを使ってロボットを動かす方法を説明していきます．

##モータ操作
本ロボットのモータとして，以下の２種類あります．

* 左右のモータ
* アームのモータ

どちらも同じAPIで制御できます．利用するAPIは，[ev3_motor_set_power()](https://www.toppers.jp/ev3pf/EV3RT_C_API_Reference/group__ev3motor.html#gaf5c96b6a7e3fdc7e13ba3466359294a0) であり，引数を変更することで制御対象モータを指定できます．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244147/518df4bb-fc4a-da5d-03fc-08fb7a6c625b.png)

##モータ操作プログラム例
では，実際にモータ操作を試してみましょう．上記のAPIを利用して，以下を実現するプログラムを書いてみてください．

1. 10秒前進
- 10秒後進
- 10秒アームUP
- 10秒アームDOWN

なお，解答例は，以下になります(先ほど`#if 1` にしたところ)．

https://github.com/toppers/hakoniwa-single_robot/blob/main/sdk/workspace/base_practice_1/app.c#L330-L351

上記は前進・後進だけでしたが，曲がる操作をしたい場合は，[ev3_motor_steer()](https://www.toppers.jp/ev3pf/EV3RT_C_API_Reference/group__ev3motor.html#ga772dadf1354388584c36ba26f3baf7cf)を使います．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244147/29d91914-5460-c844-6cda-41e112711046.png)

ブレーキ操作は，[ev3_motor_stop()](https://www.toppers.jp/ev3pf/EV3RT_C_API_Reference/group__ev3motor.html#ga27585a7d658c0a5eec3ea4d7297c4e6b)を使います．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244147/301575ca-745b-8908-6bdd-d28028645aa8.png)

##LEDライト操作
本ロボットにはLEDライトがありますので，ロボット制御の内部状態等をLEDで表現することができます．LEDライト操作は，[ev3_led_set_color()](https://www.toppers.jp/ev3pf/EV3RT_C_API_Reference/group__ev3led.html#gaa40eed1dd40c81573646f95ec8c427cb)を使います．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244147/28366c2b-cad8-f509-2e90-a40f0b28c0ac.png)


##センサ操作
本演習では以下の３種類のセンサを使います．

* カラーセンサ
* 超音波センサ
* タッチセンサ

### カラーセンサ
カラーセンサ操作は，[ev3_color_sensor_get_color()](https://www.toppers.jp/ev3pf/EV3RT_C_API_Reference/group__ev3sensor.html#ga776b35d98fd73550278e27ee39a3d3aa)，[ev3_color_sensor_get_reflect()](https://www.toppers.jp/ev3pf/EV3RT_C_API_Reference/group__ev3sensor.html#ga6f0760f8a0781fd5397f3365c6d6ac87)を使います．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244147/957b9ccf-0e06-1881-61de-ab2e44424c2f.png)

### 超音波センサ
超音波センサ操作は，[ev3_ultrasonic_sensor_get_distance()](https://www.toppers.jp/ev3pf/EV3RT_C_API_Reference/group__ev3sensor.html#ga956536aaab7677c2b512b2d3bd4e498f)を使います．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244147/4d15e93b-1702-f1f6-47e2-bebb5a713051.png)

### タッチセンサ
本ロボットのタッチセンサは，以下の２種類あります．

* 左肩側のタッチセンサ
* アーム側のタッチセンサ

タッチセンサ操作は，[ev3_touch_sensor_is_pressed()](https://www.toppers.jp/ev3pf/EV3RT_C_API_Reference/group__ev3sensor.html#ga0bd7ec7b7ac2fbaaa6cbe46eff3a829d)を使います．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244147/e0d76bb3-f129-dec8-db9c-5ca14cda7dc9.png)

#演習課題
これで基本的なロボット制御方法の説明は終わりです．

それでは，これまでのロボット制御APIを駆使して，課題をクリアしてみてください！

##課題内容
フロアの色，障害物までの距離を各種センサで検出して，ゴールまでたどり着こう．
[可能なら]
　・ロボットの内部状態でLEDカラーで変化させてみよう
　・地面に落ちているボールを運んでみよう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244147/c32ca3fc-780e-4ce7-6b7e-da0196994f05.png)

なお，app.c のデフォルトが解答例になります．

#荷物運搬用のロボット
これまでの演習では，ETロボコン競技会で使用されているHackEVモデルを使っていましたが，これとは別に荷物運搬用のロボットもあります．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244147/5608f9b0-a592-dc58-420d-4ecff58e1a96.png)

基本的な利用手順は先述の通りですが，一部異なる点ありますので，差分のみ説明します．

##Unityアプリ
本ロボットのUnityアプリは以下の方法でダウンロードしてください．

```bash
$ bash unity/download.bash auto-ride edurobo-v1.0.0/WindowsAutoRide.zip
```

##開発用フォルダ
VSCodeの開発用フォルダは以下にします．

`{単体ロボットシミュレータのインストールフォルダ}/hakoniwa-single_robot/sdk/workspace/park_ride00`

##ビルド方法
### ターミナルAでの操作
```bash
$ sudo service docker start
$ bash run-proxy.bash park_ride00
```

### ターミナルBでの操作
```bash
$ bash build-app.bash clean
$ bash build-app.bash park_ride00
```

##シミュレーション実行方法
```bash
$ bash start-unity.bash auto-ride
```

Unityアプリが起動すると以下の画面が出力されます．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244147/db0970ec-7b51-d0aa-06c6-89769414fb69.png)

##コース説明
コースは上図のとおり，オーバルコースを周回するものです．

ただし，荷物を運搬しますので，以下の荷物を用意しています．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244147/5f38e8c5-7fc7-9254-d604-0226cb9ae653.png)

荷物は，ロボットの荷台に置く必要がありますので，以下のボタンを用意しています．

* `乗車`ボタンは，荷物を荷台に移動させます．
* `降車`ボタンは，荷物を荷物を置く場所に移動します．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244147/96d1da87-e899-4a8d-add6-bf50788aae7d.png)

荷物を置く場所は，オーバルコース周辺に配置している黄色のシートです．
降車ボタンを押下すると，荷物から最も近いシートに移動します．

また，オーバルコース内には以下のように青い壁が配置されており，荷物を置く場所の手前にそれぞれ配置されています．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244147/712d499e-0eff-87e3-7030-d47e30c996a7.png)

##演習プログラム
演習内容としては，荷物を荷台に置いたらオーバルコースに沿って移動させ，荷物集積場所で降車させます．再度，荷物を乗車させた場合，次の荷物集積場所へ移動させ同じ操作を繰り返し，元の位置に戻りましょう．

演習プログラム例は，以下にありますので，ぜひ解読してみてください！

https://github.com/toppers/hakoniwa-single_robot/tree/main/sdk/workspace/park_ride00




#その他

##カメラ操作
演習中，カメラのアングルや位置を変更したくなります．

以下のマウス操作で実行できます．

* ズームアウト/ズームイン
  * マウスホイール操作
* カメラ移動
  * マウスホイール押したまま，マウス移動
* カメラアングル移動
  * マウス右クリックしたまま，マウス移動


# お知らせ：箱庭もくもく会

TOPPERS箱庭WGでは，もくもく会を不定期に開催しています．
本記事の内容を実際に試してみたい方や試してみたけど詰まっている方は，ぜひご参加ください．画面共有しながら参加者同士でサポートしたり，一緒に新しい機能を実装したりと”もくもく”しましょう．

https://hakoniwa.connpass.com/