Open-RMFのcrowd sim(人の動きをシミュレーション空間に再現する)を試してみた

# 1. はじめに
　いままで「WSL2環境下で構築したOpen-RMFで複数ロボットとエレベータの連携をシミュレーションできる環境で遊んでみる　〇〇編」とか「Open-RMFで複数ロボットとエレベータの連携をシミュレーションできる環境で、オフィスビルにおける簡単な館内配送シミュレーションをしてみた　その〇」など、いくつかのOpen-RMF関連の記事を書いてきました。
　これまでのシミュレーションでは、ロボット配送がスムーズに行われる理想的な環境を想定していました。つまり、什器の配置や人の動きといった、実際の配送で起こりうる外乱は考慮していませんでした。
　什器については、traffic-editorを使ってシミュレーション環境にモデルを読み込むことで再現できることは知っていましたが、人の動きについてはどうすれば良いか調べていたところ、Open-RMFに「crowdsim」という機能があることが分かりました。この機能を使えば、シミュレーション空間に人々の動きを再現できるため、より現実に近い状況でロボットの動作を検証できるようになると考えられます。
　そこで、このcrowdsimを試行してみた、というのがこの記事の内容です。

# 2. 実行環境
CPU: CORE i7 7th Gen
メモリ: 32GB
GPU: GeForce RTX 2070
OS: Ubuntu22.04(WSL2ではなくPCに直接インストール)
ROS2: Humble

# 3. 人の動きのみを再現してみる
## 3.1 human laneの設定
[WSL2の環境下において、Traffic-Editorを使って複数ロボットの移動をシミュレーションできる環境を構築してみた](https://qiita.com/bebebefu/items/c787bfa2d9daf04aab4c)で構築した環境においてドアや什器やロボットを消して、外壁だけの環境をまず作成します。
　そして以下の図で赤枠で囲んだ"add human lane"をクリックした後に以下のように人が動く経路(灰色の経路、1個の経路が選択状態なのでくすんだ赤色をしています)を設定します。

![humanLaneの追加.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3581920/f08a5b5d-eb70-6b0f-b8b7-26b418db41a8.png)

crowd simに関する設定は以下の図で赤枠で囲んだ"crowd"のタブをクリックして表示される画面でできます。ここで経路の幅は以下の図で黄枠で囲んだ"crow"widthで変更できます。私が今回の記事を作成する際に参考にした[[1]](#参考サイト)の設定では"width"を3にしています。今回の記事では検証をしていませんが、複数の人間の動きを再現する場合、幅を大きくすることで、人のモデル同士のすれ違いがスムーズにいくようです。

![humanlane_setting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3581920/0e26b9a8-d998-ea6c-492c-9c4e4e438936.png)

## 3.2 human_goal_set_nameの設定
前節で設定したhuman laneの頂点を選択した上で、画面右下にある"Add property"をクリックして、"human_goal_set_name"のプロパティを追加して以下の図の赤枠で囲んだところのようにそれぞれの頂点に名前を設定します。この記事では[[1]](#参考サイト)を参考に、それぞれの頂点に"crowd_goal1"、"crowd_goal2"、"crowd_goal3"、"crowd_goal4"という名前を付けました。

![goalset1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3581920/9c25a76f-4fa3-3f51-8f6c-f6c0c28a24ee.png)

![goalset2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3581920/26106bbb-6bac-4a60-8e89-b8ade2a2f654.png)

![goalset3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3581920/229393c3-8e29-7dbe-4112-46baee7dc382.png)

![goalset4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3581920/6988d927-ad90-db15-e140-e9202225fee2.png)

## 3.3 enable_crowd_simの有効化とupdate_time_stepの設定
以下の図で赤枠で囲んだenable_crowd_simのところにチェックを入れ、黄枠で囲んだupdate_time_stepの設定はデフォルトの0.1にしました。

![checck.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3581920/3d6ac0bd-3cec-3930-cd8e-e2a7dcb648a2.png)

## 3.4 GoalSetsの設定
以下の図の赤枠で囲んだ"GoalSets"の"Edit"をクリックすると、黄枠で囲んだ画面が表示されます。この画面で、前節で設定した"human_goal_set_name"を"Goal Area"に追加し、idやcapacityを図のように設定します（設定値は[[1]](#参考サイト)を参考にしました）。設定が完了したら、"OK"ボタンをクリックして画面を閉じます。なお、設定についての細かい解説は[[2]](#参考サイト)に記載がありますので、詳細についてはそちらを参考にしていただきこの記事では省略させていただきます。

![goalset_setting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3581920/358068b4-51f3-0539-7dd0-3938f3af1951.png)

## 3.5 Statesの設定
以下の図の赤枠で囲んだ"States"の"Edit"をクリックすると、黄枠で囲んだ画面が表示されます。この画面において、ゴールの状態の名前や状態遷移やGoal Set idなどを図のように設定します。設定が完了したら、"OK"ボタンをクリックして画面を閉じます。なお、設定についての細かい解説は[[2]](#参考サイト)に記載がありますので、詳細についてはそちらを参考にしていただきこの記事では省略させていただきます。

![states.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3581920/48abeea8-d927-f0da-5310-d8abfd0d0a30.png)

## 3.6 Transitionsの設定
以下の図の赤枠で囲んだ"Transitions"の"Edit"をクリックすると、黄枠で囲んだ画面が表示されます。この画面において、前節で設定した"States"についての設定をしていきます。

![transition_first.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3581920/ecf32b2d-eeb0-4536-e49f-f7acaf19755b.png)

以下の図で赤枠で囲んだ"crowd_goal_state1"の"ToSate edit"の"edit"をクリックすると、以下の図の黄枠で囲んだ画面が表示されます。この画面において各stateの"Weight"に数値を設定することで、シミュレーションにおける人の移動先の割合を調整できるそうです。この記事での設定値は[[1]](#参考サイト)を参考に設定しました。設定が完了したら、"OK"ボタンをクリックして画面を閉じます。なお、シミュレーションでは、この重みに基づいて人がランダムに移動先を選ぶ仕組みになっているそうです。ただし、私はドキュメントを十分に確認できていないため、この説明に誤りがある可能性があります。そのため、正確なことについては[[2]](#参考サイト)の「Transitions」の項を参考にしていただきたくお願いします。

![transition_second.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3581920/d4087735-fb6a-32c5-cf73-70e43d69c636.png)

次に以下の図で赤枠で囲んだ"crowd_goal_state1"の"Condition edit"の"edit"をクリックすると、以下の図の黄枠で囲んだ画面が表示されます。ここの設定は[[1]](#参考サイト)での設定をそのまま適用し、図のようにしました。なお、設定についての細かい解説は[[2]](#参考サイト)の「Transitions」の項に記載がありますので、詳細についてはそちらを参考にしていただきこの記事では省略させていただきます。

![transition_third.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3581920/1bd1e734-54a5-b827-b36d-456aa0ee78c0.png)


## 3.7 AgentProfilesの設定
以下の図で赤枠で囲んだ"AgentProfiles"の"edit"をクリックします。

![拡大図 - コピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3581920/7082b618-9f58-72ba-04c7-028ac4465e22.png)

次に表示される画面において、赤枠で囲まれた部分の設定値を[[1]](#参考サイト)に記載されている値に合わせ、図のように設定しました。設定が完了したら、"OK"ボタンをクリックして画面を閉じます。

![agentprofile.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3581920/b9f06302-dc7f-87bb-2f13-4f1de7c32849.png)

## 3.8 AgentGroupsの設定
以下の図で赤枠で囲んだ"AgentGroups"の"edit"をクリックします。
![拡大図 - コピー - コピー - コピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3581920/b937207c-8c77-9a64-6323-7d35ecc5b655.png)

次に表示される画面において、赤枠で囲まれた部分の設定値は[[1]](#参考サイト)に記載されていた値を参考に図のように設定しました。なお、point_xとpoint_yの値は"crowd_goal1"の座標の値を入力しました。設定が完了したら、"OK"ボタンをクリックして画面を閉じます。
![agentgroups.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3581920/ee4c0cdf-4a96-1a5d-077d-1f93d3a78444.png)

## 3.9 ModelTypesの設定
以下の図で赤枠で囲んだ"Modeltype"の"edit"をクリックします。
![model.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3581920/7025af6a-480d-4f65-4221-f8a4a50097b2.png)

次に表示される画面において、赤枠で囲まれた部分の設定は[[1]](#参考サイト)を参考に図のように設定しました。設定が完了したら、"OK"ボタンをクリックして画面を閉じます。
![modeltype.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3581920/9242457f-5a2f-bd22-dfec-b42ad4507c46.png)

## 3.10 ビルドとシミュレーション結果
上記の手順が終わったら、以下のコマンドでビルドしました。
```:terminal
cd ~/rmf_ws
source /opt/ros/humble/setup.bash
export CXX=clang++
export CC=clang
colcon build 
```
そしてビルド完了後、以下のコマンドでシミュレーション環境を起動しました。なお、今回の環境はevtest_crowdという名前にしました。
```:terminal
cd ~/rmf_ws
source ~/rmf_ws/install/setup.bash
ros2 launch rmf_demos_gz_classic evtest_crowd.launch.xml use_crowdsim:=1
```
そしてシミュレーションした結果が以下の動画です。MaleVisitorPhoneという名前のモデルが一人で歩き回っている様子を再現できました。

<iframe width="560" height="315" src="https://www.youtube.com/embed/f0RHYaSnL-k?si=FcI0fsrhNP4MBFfe" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>


# 4. 人が動く経路上にドアを設置してみる
人が動く経路上に以下の図で赤枠で囲んだところにヒンジ式のドアを設置してみました。
![door設置.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3581920/a22cca6a-3168-9060-485d-56b80214e39d.png)

そしてシミュレーションした結果が以下の動画です。ドアはシミュレーション空間内では半透明の茶色い長方形として表現されています。MaleVisitorPhoneという名前のモデルが、ドアをすり抜けてしまうことが確認できました。Open-RMFのドアのpluginとcrowd simは連携していないようです。
<iframe width="560" height="315" src="https://www.youtube.com/embed/Ofg2XTQaSb0?si=FcI0fsrhNP4MBFfe" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

# 5. 人が動くシミュレーション空間にロボット（tinyRobot）を追加してみる
人が動く経路上に以下の図で緑線で示したようにロボットの経路を追加しました。ちょうど漢字の「中」のような形です。
![Screenshot from 2024-08-04 09-35-23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3581920/0c986b7b-a489-856d-31cd-41bd851a0c0d.png)

そしてシミュレーションした結果が以下の動画でして、人とロボットの接触が回避された場合です。衝突しそうになった時にtinyRobot側が止まる（減速する）ような様子が見られました。
<iframe width="560" height="315" src="https://www.youtube.com/embed/iQLSKsIKmPE?si=FcI0fsrhNP4MBFfe" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

そして衝突した場合が以下の動画です。衝突したどちらもその場で止まってしまいました。
<iframe width="560" height="315" src="https://www.youtube.com/embed/pHokCfN5vvI?si=FcI0fsrhNP4MBFfe" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

# 6. 人が動くシミュレーション空間をロボット（tinyRobot）とエレベータが連携して複数階移動できる環境を追加構築した場合

以下の図のようにロボット（tinyRobot）とエレベータが連携して複数階移動できる環境を構築しました。単純に前章で構築した環境にエレベータを追加して2階に行けるようにしました。なお、この環境の構築の方法は[WSL2の環境下において、Traffic-Editorを使って複数ロボットとエレベータの連携をシミュレーションできる環境を構築してみた](https://qiita.com/bebebefu/items/32dcb43db1213e1a00e0)に詳細がありますので、そちらを参照いただきたくお願いします。
![Screenshot from 2024-08-04 09-58-14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3581920/49dce2d4-43f0-d5ca-0e64-cc6255878d04.png)

そしてこの環境をビルドして、起動したところ以下の図のようになってしまい、**人が消えてしまいました!!**。
![Screenshot from 2024-08-04 09-44-51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3581920/5eddde47-c0cb-b7fa-2dde-e52b459a3944.png)

そしてエレベータを消し、2階も消して再ビルドしたところ、人がまた以下の図のようにシミュレーション環境に再現されました。そのため人が消えた原因はエレベータにあるようです。

![Screenshot from 2024-08-04 10-02-17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3581920/81588268-9ab9-811c-f3a1-9fbef600fddb.png)

この事象なんですが、[WSL2の環境下において、Traffic-Editorを使って複数ロボットとエレベータの連携をシミュレーションできる環境を構築してみた](https://qiita.com/bebebefu/items/32dcb43db1213e1a00e0)で構築したシミュレーション環境に、crowd simのタブから人の通行経路を設定しても、人だけがシミュレーション空間に再現されませんでした。

# 7. まとめ　
　今回の試行により、crowd simの設定方法がある程度は理解できました。しかし、エレベータを追加するとシミュレーション空間から人が消えるという現象が発生したことから、**Open-RMFにおいてはエレベータ（Lift plugin）とcrowd simは共存できない**可能性があると考えられます。またドアも人はすり抜けてしまうことから、**Open-RMFにおいてはドア（Door plugin）とcrowd simは共存できない**可能性があることも考えられます。
　ただ、crowd simに関するドキュメントやQ&Aは英語でもほとんどないため、この事象が私の環境特有の問題なのか、それともバグなのかを断定することは難しい状況です。今後、さらなる調査を進めていく必要があると思います。

# 参考サイト
[1] [https://github.com/open-rmf/rmf_demos/tree/humble?tab=readme-ov-file#airport-terminal-world](https://github.com/open-rmf/rmf_demos/tree/humble?tab=readme-ov-file#airport-terminal-world)
[2] [https://github.com/FloodShao/crowd_simulation/blob/master/crowd_simulation_doc/crowd_simulation_usage.md](https://github.com/FloodShao/crowd_simulation/blob/master/crowd_simulation_doc/crowd_simulation_usage.md)