Rover製作16 シミュレーション環境を動かす

# 環境

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

| 項目 |	値 |
|:--|:--|
| CPU | Core i5-8250U |
| Ubuntu | 22.04 |
| ROS2 | Humble |

# 概要
ここまでEspressoFrameの実機の作り方を説明してきましたが、ここではSW開発用のシミュレーション環境の説明をします。

# 前提知識

## シミュレーション
ここでは実機と同様にsample_appを動かして機体やパンチルトを移動させることを目標とします。

## JoyPad
実機ではFutabaのT6Kのプロポを使って機体を動かしましたが、実機ではJoyPadを使います。ただし種類によってデフォルトのキーの割り当てが違ったりしてなかなか面倒です。
今回は「ロジクール ゲームパッド F310」 を用意してください。

![31sK6QwZh+L._AC_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254442/be2454c1-57cd-dfb2-9f0e-a380367aa071.jpeg)

## gazebo


# Gazeboシミュレーション
今回使うソースコードは[espresso_frame_gazebo](https://github.com/project-srs/espresso_frame_gazebo)パッケージにあります。

```shell
git@github.com:project-srs/espresso_frame_gazebo.git
```

でコードを取得してください。

## 主なソースコード

```python:espresso_frame_gazebo_launch/launch/gazebo.launch.py
"""Launch Gazebo server and client with command line arguments."""

from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.substitutions import LaunchConfiguration
from ament_index_python.packages import get_package_share_directory, get_package_share_path
from launch_ros.actions import Node, SetParameter
from launch_ros.parameter_descriptions import ParameterValue
from launch.conditions import IfCondition
from launch.substitutions import Command

def generate_launch_description():
    return LaunchDescription(
        [
            DeclareLaunchArgument(
                name="world", default_value="cafe.world", description="world file name"
            ),
            DeclareLaunchArgument(
                'sample_app', default_value='false'
            ),
            SetParameter(name="use_sim_time", value=True),
            IncludeLaunchDescription(
                PythonLaunchDescriptionSource(
                    [
                        get_package_share_directory("gazebo_ros"),
                        "/launch/gzserver.launch.py",
                    ]
                ),
                launch_arguments={
                    "world": LaunchConfiguration("world"),
                    "verbose": "true",
                }.items(),
            ),
            IncludeLaunchDescription(
                PythonLaunchDescriptionSource(
                    [
                        get_package_share_directory("gazebo_ros"),
                        "/launch/gzclient.launch.py",
                    ]
                ),
                launch_arguments={"verbose": "true"}.items(),
            ),
            Node(
                package="joy",
                executable="joy_node",
                remappings=[("joy", "/device/mavros/rc_joy/joy")],
                output="screen",
            ),
            Node(
                package='robot_state_publisher',
                executable='robot_state_publisher',
                parameters=[{'robot_description': ParameterValue(Command(['xacro ', str(get_package_share_path('espresso_frame_gazebo_launch')) + '/urdf/all.urdf']))}],
            ),
            Node(
                package="espresso_frame_gazebo_launch",
                executable="sample_app.py",
                output="screen",
                namespace="/app",
                condition=IfCondition(LaunchConfiguration('sample_app')),
            ),
        ]
    )
```

`SetParameter(name="use_sim_time", value=True)`はlaunch内のノードすべてにパラメーターを適用するコマンドです。gazeboの出すclock(起動時0から始まる)に合わせて全ノードが動きます。

## 実行

```shell:1つ目のターミナル
ros2 launch espresso_frame_gazebo_launch gazebo.launch.py sample_app:=true
```

```shell:2つ目のターミナル
rviz2 --ros-args -p use_sim_time:=true
```

rvizではtfの表示とglobal frameをodomに変更しています。
F310のAボタンを押すとarm指令を出して移動可能になり、右スティックで移動、左スティックでPanTiltが動きます。

![simulation_gazebo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254442/8981ba9c-da72-2d15-d0cb-54ce539c491c.png)


# Simpleシミュレーション

## 主なソースコード

```shell:espresso_frame_gazebo_launch/launch/simple.launch.py
from ament_index_python.packages import get_package_share_directory, get_package_share_path
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.substitutions import LaunchConfiguration
from launch.substitutions import Command
from launch.conditions import IfCondition
from launch_ros.parameter_descriptions import ParameterValue
from launch_ros.actions import Node

def generate_launch_description():
    return LaunchDescription(
        [
            DeclareLaunchArgument(
                'sample_app', default_value='false'
            ),
            Node(
                package="espresso_frame_simple_simulator",
                executable="dummy_move",
                namespace="/device",
                output="screen",
            ),
            Node(
                package="espresso_frame_simple_simulator",
                executable="dummy_turret",
                namespace="/device",
                output="screen",
            ),
            Node(
                package="joy",
                executable="joy_node",
                remappings=[("joy", "/device/mavros/rc_joy/joy")],
                output="screen",
            ),
            Node(
                package='robot_state_publisher',
                executable='robot_state_publisher',
                parameters=[{'robot_description': ParameterValue(Command(['xacro ', str(get_package_share_path('espresso_frame_gazebo_launch')) + '/urdf/all.urdf']))}],
            ),
            Node(
                package="espresso_frame_gazebo_launch",
                executable="sample_app.py",
                output="screen",
                namespace="/app",
                condition=IfCondition(LaunchConfiguration('sample_app')),
            ),
        ]
    )
```

## ビルド&実行

```shell:1つ目のターミナル
ros2 launch espresso_frame_gazebo_launch simple.launch.py sample_app:=true
```

```shell:2つ目のターミナル
rviz2
```

gazeboはないのでrviz画面だけです。gazeboと同様にjoyで操作が出来ます。

![simulation_simple.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254442/19db8c6e-92a4-579d-f5c3-ee00be19e837.png)

# 目次ページへのリンク
[Rover製作目次へのリンク](https://qiita.com/srs/items/8d0f5ac242b6ff87a006)