【ROS, unity】urdf-importerで読み込んだロボットのメッシュが表示されなくなる問題の解決方法

お疲れ様です。秋並です。

urdf-importerはurdfファイルを読み込み、ロボットモデルをunity空間上できる便利なパッケージですが、<font color="red">読み込むurdfファイルによっては、ロボットのメッシュが途中で表示されなくなる不具合が発生します。</font>

<br>

具体的には、最初に読み込んだ際は下図のように正しいモデルが生成されるのですが、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2030125/5b6519dc-4aeb-b378-afae-ab1d8701ce17.png)

<br>

しばらく時間がたつと、生成されたロボットモデルの一部が表示されなくなることがあります（特に、unityプロジェクトを再起動するとほぼ100％発生します）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2030125/a8966b78-d2a0-db06-8b92-3949a1d6d0eb.png)

<br>

今回は、この不具合の解決方法を解説します。

解決方法としては以下の2パターンがあります。

- 方法1：collision領域をプリミティブな形状にする
- 方法2：メッシュファイルの容量を削減する

# 方法1：collision領域をプリミティブな形状にする

この問題は、collision部分の読み込みに時間がかかる、具体的には<font color="red">collision部分に設定されるmeshファイルの容量が大きい場合に高確率で発生</font>します。

<br>

そのため、<font color="red">collsion部分に設定する形状を</font>メッシュファイルではなく、<font color="red">boxなどのプリミティブな形状に変更する</font>ことで対応することができます。

```xml
  <collision>
    <origin xyz="0 0 0" rpy="0 0 0"/>
    <geometry>
      <box size="0.1 0.1 0.1"/> <!--collisionのgeometryはプリミティブな形状に変更する-->
      <!--<mesh filename="$(find mobile_robot_universal_plate_description)/meshes/base_link.stl" scale="0.001 0.001 0.001"/>-->
    </geometry>
  </collision>
```
::: note
あくまで、collision部分の処理が関係しているため、visualはプリミティブな形状に変更せずに、そのままでOKです（メッシュファイルの容量がすごく大きければvisualにも影響するかもしれませんが、私の環境では10MB程度の容量ならば影響は出ていません）。
:::

<br>

この際に、cadソフトなどで確認し

collision領域の位置やサイズを設定するのがスタンダードだと思いますが、

最近はfusion2urdfなどを使用し、

自動的に3dモデルからurdfファイルを生成することも多いので、

わざわざ位置関係を計算するのが面倒なこともあるとおもいます。

<br>

その場合は、

1. collisionのgeometryには、とりあえず適当なサイズのプリミティブな図形を設定
2. unity上で位置/サイズを調整
3. 調整した結果をurdfファイルに反映

といった手順を踏めばわざわざ計算しなくても調整が可能です。

<br>

具体的には、以下の手順になります

## 1. collisionのgeometryには、とりあえず適当なサイズのプリミティブな図形を設定

unityで読み込むurdfファイルのcollisionのgeomtryに適当なサイズのプリミティブな図形を設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2030125/ddabc003-453e-2255-ca65-df24ea86428b.png)


## 2. 適当に設定したurdfを読み込んでモデルを生成し、unity上でサイズや位置を調整

1.で設定したurdfファイルをurdf-importerを使用して、unity上にスポーンします。

<br>

最初は、下図のように適当な位置に衝突領域が表示されると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2030125/4630361f-32b7-0749-ebf2-7489e020a3e4.png)

<br>

次に、InspectorでPosition, Rotation, Scaleを任意の位置に設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2030125/794b1163-0305-ce18-1479-ec8517045d06.png)


## 3. 調整した後の位置をurdfファイルに反映

最後に、unityで設定したサイズ/位置情報をurdfに反映します。

<br>

この際、unityとurdfでx,y,zの順番や符号が下図のように異なることに注意してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2030125/02c1cb56-53c3-7e4f-ba60-680493ebf7f4.png)
※ unityを(x, y, z)とすると、urdfは(z, -x, y) になります

<br>

urdfを保存し、再度urdf-importerで読み込んだ時に、期待した位置に衝突領域が表示されていればOKです。

# 方法2：メッシュファイルの容量を削減する

<font color="red">手順1の方法は</font>、衝突領域がプリミティブな図形で問題ない場合は有効ですが、例えばロボットアームなどのように、<font color="red">衝突判定ができるだけ厳密な方がよい場合には適用できません</font>。

<br>

<font color="red">この場合は、メッシュファイルの容量を削減することで対応</font>します。

<br>

メッシュファイルの容量を削減する方法にはいろいろありますが、
ここではblenderの<font color="red">「Decimate(デシメート)モディファイアー」</font>機能を使用する方法を紹介します。

<br>

最初に、要領を削減したいメッシュファイルをBlenderで読み込みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2030125/e25ef89d-a4a3-70b6-103f-5d81017b3d09.png)

<br>

「Add modifier」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2030125/0f90ccec-3718-ea77-709c-53867cc8a2a7.png)

<br>

「Generate」→「Decimate」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2030125/8be2618a-be47-b32e-20ce-7881135191b4.png)


<br>

Ratioを設定します（<font color="red">Ratioが0に近いほど</font>、ポリゴン数が減り、<font color="red">メッシュファイルの容量が削減</font>されます）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2030125/9b27cffe-df8b-f600-a023-be01b8135b14.png)

<br>

最後に、ポリゴン数を削減したモデルをexportすれば完了です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2030125/7c649550-57ae-04bc-3d7c-2f2f86e2aa07.png)


::: note
詳しく調べたわけではないですが、<font color="red">1MB未満程度まで削減すれば、unity上でメッシュが表示されなくなる不具合が発生しなくなる</font>印象です。
:::

</aside>

# さいごに

今回は、unityでメッシュが表示されなくなる不具合の解決方法を解説しました。

ROSの標準のシミュレーションはgazeboですが、UI周りはunityの方が作りやすい部分もあるので、unityでROSのシミュレーションを試したい人は参考にしてみてください。

# 参考サイト
- [Blenderで3Dモデルを軽量化してみよう](https://creator.cluster.mu/2023/01/11/blender-3dweight/)