ROS講座37 gazebo worldを作成する

# 環境
この記事は以下の環境で動いています。

| 項目 | 値 |
|:-:|:-:|
| CPU | Core i5-8250U |
| Ubuntu | 20.04 |
| ROS | Noetic |
| Gazebo | 11.9.0 |

インストールについては[ROS講座02 インストール](https://qiita.com/srs/items/e0e0a9dc3f94c2d3348e)を参照してください。
またこの記事のプログラムはgithubにアップロードされています。[ROS講座11 gitリポジトリ](https://qiita.com/srs/items/25a56a6abda41dcf396e)を参照してください。

# 概要
gazeboの世界にはロボット以外にもいろいろな物体を置くことが出来ます。gazeboを起動した後にGUI上で物を配置することもできるのですが、gazeboのworldファイルを記述することで起動時から物を配置することが出来ます。
worldファイルはSDFというフォーマットで記述します。今回はこの書き方を紹介します。

# GazeboとROSの関係
両者がなにか混同しやすいのでまとめます

* ROS: (中心は)ロボットミドルウェア
    * 通信フレームワーク: pubsubの通信を行う
    * 起動フレームワーク：roslaunchで設定した起動を行う
* Gazebo: 物理シミュレーター
    * 基本機能: 記述されたWorldに従って物理シミュレーションを行う
    * Plugin: 拡張機能を使ってWorldに相互作用が出来る

つまりROSとGazeboは全くの別物で、Gazebo単体で(=ROSが無くても)起動できます。ただROSとの接続性のためにroslaunch経由でGazeboを起動したり、gazeboのpluginでセンサー情報をrosトピックでpublishできたりします。

世の中のGazeboシミュレーションの解説だとROS前提でurdfでworldのmodelを記述したりしますが、ここではできる限りGazeboを純粋に触るためにSDFでWorldを記述して、後々urdfとの連携を解説します。

# worldファイルの記述

## worldファイル
ROSではモデルを定義するのにurdfという形式で記述しますが、gazeboではsdfという形式を使用します。形式は違いますが、両方とも同じような設計思想で、ほぼ1対1で対応します。
全ての物体はmodelとして定義されます。worldファイルではこのmodelを呼び出したり環境の設定をします。記述は本来はいろいろと複雑なのですが、今回はモデルの呼び出しをするだけの単純な例を示します。

```xml:gazebo1_lecture/worlds/world_first_launch.world
<?xml version="1.0" ?>
<sdf version="1.5">
  <world name="default">
    <include>
      <uri>model://sun</uri>
    </include>
    <include>
      <uri>model://ground_plane</uri>
    </include>
    <include>
      <name>beer0</name>
      <uri>model://coke_can</uri>
      <static>true</static>
      <pose>2 1 0 0 0 0</pose>
    </include>
  </world>
</sdf>
```

* `<include>`タグでモデルを呼び出します。初期状態では~/.gazebo/model以下にあるモデルのみを呼び出せます。     
* `<uri>model://sun</uri>`は呼び出すモデルを参照します。`sun`と`ground_plane`はデフォルトのgazeboワールドにもある要素です。とりあえず入れておきましょう。
* `<name>beer0</name>`はモデルに名前を付けるタグです。省略可能ですが、同じモデルを複数呼び出すときは必須です。
* `<pose>1 0 0 0 0 0</pose>`はモデルの出現位置を決めるタグです。順番にx軸位置、x軸位置、x軸位置、roll回転、pitch回転、yaw回転を表します。回転の単位はdegです。
* `<static>false</static>`はモデルを固定するかどうかを決めるタグです。省略するとfalseになります。falseだと物理演算が適用されぶつかれば動きますし、重力の影響を受けます。trueにすると空間に固定されます。poseでz軸位置を1.0などと指定すれば、空中に浮きます。ぶつかっても動きません。

# 実行
いくつかの実行方法があります。

## gazebo単体で起動
`gazebo (worldファイル)`とするとworldファイルを指定してgazeboを起動することができます。worldファイルのデバッグをするときなどに便利ですが、ROSと一緒に使うには不向きです。

```shell:worldを指定してgazeboを起動
roscd gazebo1_lecture/worlds/
gazebo world_first_launch.world
```

![sim3_world1.png](https://qiita-image-store.s3.amazonaws.com/0/254442/11e0dbe8-d339-8aed-5c4f-024c3c8969fa.png)

ちなみにこの方法で起動すると、ターミナルで`Ctrl+C`をしてgazeboを落とそうとすると時間がかかります。GUIの×ボタンを押しましょう。

## ROSのlaunchから実行（フルパスで指定）

gazebo_rosパッケージにあるempty_world.launchのargのworld_nameでworldファイル名を指定します。しかしこれはフルパスまたはGAZEBO_RESOURCE_PATHに通っているworldファイルしか読み込んでくれません。

```shell:worldを指定してgazeboを起動
roscd gazebo1_lecture/worlds/
roslaunch gazebo_ros empty_world.launch world_name:=`pwd`/world_first_launch.world 
```

## ROSのlaunchから実行（環境変数でパスを通す）

```shell:worldを指定してgazeboを起動
roscd gazebo1_lecture/worlds/
export GAZEBO_RESOURCE_PATH=$GAZEBO_RESOURCE_PATH:`pwd`
roslaunch gazebo_ros empty_world.launch world_name:=world_first_launch.world 
```

## ROSのlaunchから実行（package.xmlでパスを通す）

ROSを使うならこの方法が一番です。

```xml:gazebo1_lecture/package.xmlに追加
  <exec_depend>gazebo_ros</exec_depend>

  <export>
    <gazebo_ros gazebo_media_path="${prefix}/worlds" />
  </export>
</package>
```

ファイルを編集したら以下を実行します。
各ターミナルごとに実行前に`source ~/catkin_ws/devel/setup.bash`を実行する必要があります。

```shell:worldを指定してgazeboを起動
roslaunch gazebo_ros empty_world.launch world_name:=world_first_launch.world 
```

# coke缶が出てこないときは
coke_canがローカルに保存されている（~/.gazebo/models以下にcoke_canというディレクトリがある）場合でないと表示されません。
無いなら以下の方法で操作をして一度gazebo上に表示させることでローカルにキャッシュする必要があります。

* gazeboを開く
* 左側のウィンドウでInsertタブ開く
* http://models.gazebosim.org/... を押す
* 数分待つ
* http://...の左側に▲マークが出るんで押す
* Coke Canを選択する
* 3D viewの中を選択して出現させる

その中から「Coke Can」を選んで配置してみてください。

# 参考
[環境を作ろう](http://cir-kit.github.io/blog/2015/02/05/gazebo-population-of-models/)
[Gazebo + ROS で自分だけのロボットをつくる](https://qiita.com/RyodoTanaka/items/af834ed767589a02e27a)
[Gazeboによるマニピュレータのシミュレーション](https://sites.google.com/site/robotlabo/time-tracker/ros/gazebo_mani?tmpl=%2Fsystem%2Fapp%2Ftemplates%2Fprint%2F&showPrintDialog=1)

# 目次ページへのリンク
[ROS講座の目次へのリンク](https://qiita.com/srs/items/5f44440afea0eb616b4a)