ROSの勉強　第49弾：Xacro作成のまとめ: 独立差動二輪車の構築（URDFを体系化）

# #プログラミング ROS< Xacro作成のまとめ: 独立差動二輪車の構築（URDFを体系化） >

## はじめに
ROS(Robot Operating System)をさらに扱えるようになることが目的である．その第49弾として，「Xacro作成のまとめ: 独立差動二輪車の構築（URDFを体系化）」を扱う．

## 環境
##### Docker環境（VScode + Windows10）
<details><summary>Dockerfile</summary>

```dockerfile:Dockerfile
FROM osrf/ros:noetic-desktop-full

WORKDIR /root/

ENV DISPLAY host.docker.internal:0.0

RUN apt-get update -y && apt-get upgrade -y
RUN apt-get install x11-apps -y
RUN echo "source /opt/ros/noetic/setup.sh" >> .bashrc
RUN mkdir -p catkin_ws/src
RUN cd catkin_ws/src && . /opt/ros/noetic/setup.sh && catkin_init_workspace
RUN cd && cd catkin_ws && . /opt/ros/noetic/setup.sh && catkin_make
RUN echo "source ./catkin_ws/devel/setup.bash" >> .bashrc

RUN apt-get update -y && apt-get upgrade -y && apt-get install git -y
```

</details>


<details><summary>devcontainer.json</summary>


```json:devcontainer.json
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.224.3/containers/docker-existing-dockerfile
{
	"name": "Existing Dockerfile",

	// Sets the run context to one level up instead of the .devcontainer folder.
	"context": "..",

	// Update the 'dockerFile' property if you aren't using the standard 'Dockerfile' filename.
	"dockerFile": "../Dockerfile",

	// Set *default* container specific settings.json values on container create.
	"settings": {},
	
	// Add the IDs of extensions you want installed when the container is created.
	"extensions": [
		"ms-python.python",
		"ms-python.vscode-pylance",
		"ms-iot.vscode-ros"
	],

	"workspaceFolder": "/root/",

	"mounts": [
		"source=${localWorkspaceFolder}/share,target=/root/share,type=bind",
	],
	// // Use 'forwardPorts' to make a list of ports inside the container available locally.
	// // "appPort": ["11411:11411"],

	// // Uncomment the next line to run commands after the container is created - for example installing curl.
	// // "postCreateCommand": "apt-get update && apt-get install -y curl",

	// // Uncomment when using a ptrace-based debugger like C++, Go, and Rust
	"runArgs": ["--gpus=all"],

	// Uncomment to use the Docker CLI from inside the container. See https://aka.ms/vscode-remote/samples/docker-from-docker.
	// "mounts": ["source=../src/,target=/root/src,type=bind"],
	// "mounts": [ "source=../src,target=/root/src,type=bind" ],

	// Uncomment to connect as a non-root user if you've added one. See https://aka.ms/vscode-remote/containers/non-root.
	// "remoteUser": "vscode"
}

```

</details>

**参考**

https://qiita.com/Yuya-Shimizu/items/22c6a2a473139d15857f


##### コンピュータ
|||
|:-:|:--|
|デバイス|MSI|
|プロセッサ|Intel(R) Core(TM) i5-7300HQ CPU @ 2.50GHz 2.50GHz|
|実装RAM|16.0 GB (15.9 GB 使用可能)|
|OS|Windows (Windows 10 Home, バージョン：22H2)|

##### ROS
|||
|:-:|:--|
|Distribution|noetic|

## 概要
前々回にURDFにて作成した独立差動二輪車のモデルをXacroで作り直すことで，体系化を図る．

https://qiita.com/Yuya-Shimizu/items/1fd238211ed35d187e10

ここでは，４つのステップに分けて，順番に体系化をおこなう．

1. 必要なパーツの作成
1. ジョイントの作成
1. Gazeboでのマテリアル設定
1. 差動駆動プラグインの設定
1. LiDARプラグインの設定

## Xacroでの作成
### STEP0: ロボットの設計
XacroもURDF同様，構築していくにあたって非常に重要になってくるものが，事前の設計である．
（パーツの構成，各パーツの寸法，各パーツ間の位置関係およびつなぎ方）

![model_design_ver3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951300/9dab32e5-9367-4392-897b-97668ce12cd8.png)

今回は，LiDAR付き独立差動二輪車を作成していく．

### STEP1: 必要なパーツの作成
ここでは，各パーツの「見た目」「衝突判定」「慣性モーメント」についての設定を記述する．
ただし，各パーツの共通部分はマクロとして表現する．

<details><summary>material_colors.xacro</summary>

```xml:Xacro
<?xml version="1.0"?>
<robot xmlns:xacro="http://ros.org/wiki/xacro">

<!-- Define Material Colors -->
<material name="white">
    <color rgba="1.0 1.0 1.0 1.0"/>
</material>

<material name="red">
    <color rgba="1.0 0.0 0.0 1.0"/>
</material>

<material name="green">
    <color rgba="0.0 1.0 0.0 1.0"/>
</material>

<material name="blue">
    <color rgba="0.0 0.0 1.0 1.0"/>
</material>

<material name="yellow">
    <color rgba="1.0 1.0 0.0 1.0"/>
</material>

<material name="cyan">
    <color rgba="0.0 1.0 1.0 1.0"/>
</material>

<material name="purple">
    <color rgba="1.0 0.0 1.0 1.0"/>
</material>

<material name="black">
    <color rgba="0.0 0.0 0.0 1.0"/>
</material>

</robot>
```

</details>

<details><summary>parts_macro.xacro</summary>

```xml:Xacro
<?xml version="1.0"?>
<robot xmlns:xacro="http://ros.org/wiki/xacro">

<xacro:macro name="link_generator" params="name mass color_name *shape *inertia">
    <link name="${name}">
        <visual>
            <geometry>
                <xacro:insert_block name="shape" />
            </geometry>
            <material name="${color_name}"/>
        </visual>
        <collision>
            <geometry>
                <xacro:insert_block name="shape" />
            </geometry>
        </collision>
        <!--慣性-->
        <inertial>
            <mass value="${mass}"/>
                    <xacro:insert_block name="inertia" />
        </inertial>
    </link>
</xacro:macro>

</robot>
```

</details>

<details><summary>robot_v01.xacro</summary>

```xml:Xacro
<?xml version="1.0"?>
<robot xmlns:xacro="http://ros.org/wiki/xacro" name="diff_drive_robot">

	<xacro:include filename="$(find diff_drive_pkg)/xacro/material_colors.xacro" />
	<xacro:include filename="$(find diff_drive_pkg)/xacro/parts_macro.xacro" />

	<!-- ############## リンクの生成 ############### -->
	<!-- ボディ -->
	<xacro:link_generator name="body" mass="1.0" color_name="red">
        <cylinder radius="0.2" length="0.15" />
        <inertia ixx="0.0118750" iyy="0.0118750" izz="0.0200000" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>
	<!-- 左車輪 -->
	<xacro:link_generator name="wheel_left" mass="0.5" color_name="blue">
		<cylinder radius="0.15" length="0.05"/>
        <inertia ixx="0.0029167" iyy="0.0029167" izz="0.0056250" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>
	<!-- 右車輪 -->
	<xacro:link_generator name="wheel_right" mass="0.5" color_name="blue">
		<cylinder radius="0.15" length="0.05"/>
        <inertia ixx="0.0029167" iyy="0.0029167" izz="0.0056250" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>
	<!-- 前方キャスター -->
	<xacro:link_generator name="caster_forward" mass="0.5" color_name="green">
		<sphere radius="0.05"/>
        <inertia ixx="3.000e-4" iyy="3.000e-4" izz="3.000e-4" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>
	<!-- 後方キャスター -->
	<xacro:link_generator name="caster_backward" mass="0.5" color_name="black">
		<sphere radius="0.05"/>
        <inertia ixx="3.000e-4" iyy="3.000e-4" izz="3.000e-4" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>
	<!-- LiDAR台 -->
	<xacro:link_generator name="lidar_base" mass="0.15" color_name="yellow">
		<box size="0.1 0.1 0.1"/>
		<inertia ixx="0.25" iyy="0.25" izz="0.25" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>
	<!-- LiDAR -->
	<xacro:link_generator name="lidar_link" mass="0.05" color_name="purple">
		<cylinder radius="0.05" length="0.05"/>
		<inertia ixx="0.125" iyy="0.125" izz="0.188" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>

</robot>
```

</details>

``material_colors.xacro``：色情報に関するマクロファイル．
``parts_macro.xacro``　　：パーツに関するマクロファイル．
``robot_v01.xacro``　　　：2つのマクロファイルで全てのパーツを作成するマクロファイル．

### STEP2: ジョイント設定の追加
ここでは，各パーツ間の関係を表現するジョイントの設定を記述する．
ただし，各ジョイント設定の共通部分はマクロとして表現する．

<details><summary>joints_macro.xacro</summary>

```xml:Xacro
<?xml version="1.0"?>
<robot xmlns:xacro="http://ros.org/wiki/xacro">

<xacro:macro name="fixed_joint" params="name parent child *origin">

	<joint name="${name}" type="fixed">
    <xacro:insert_block name="origin" />
    <parent link="${parent}"/>
    <child link="${child}"/>
 	</joint>

</xacro:macro>

<xacro:macro name="continuous_joint" params="name parent child *origin *axis">

	<joint name="${name}" type="continuous">
    <xacro:insert_block name="origin" />
    <parent link="${parent}"/>
    <child link="${child}"/>
    <xacro:insert_block name="axis" />
 	</joint>

</xacro:macro>

</robot>
```

</details>


<details><summary>robot_v02.xacro</summary>

```xml:Xacro
<?xml version="1.0"?>
<robot xmlns:xacro="http://ros.org/wiki/xacro" name="diff_drive_robot">

	<xacro:include filename="$(find diff_drive_pkg)/xacro/material_colors.xacro" />
	<xacro:include filename="$(find diff_drive_pkg)/xacro/parts_macro.xacro" />
	<xacro:include filename="$(find diff_drive_pkg)/xacro/joints_macro.xacro" />

	<!-- ############## リンクの生成 ############### -->
  <link name="base_link"/>
	<!-- ボディ -->
	<xacro:link_generator name="body" mass="1.0" color_name="red">
        <cylinder radius="0.2" length="0.15" />
        <inertia ixx="0.0118750" iyy="0.0118750" izz="0.0200000" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>
	<!-- 左車輪 -->
	<xacro:link_generator name="wheel_left" mass="0.5" color_name="blue">
		<cylinder radius="0.15" length="0.05"/>
        <inertia ixx="0.0029167" iyy="0.0029167" izz="0.0056250" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>
	<!-- 右車輪 -->
	<xacro:link_generator name="wheel_right" mass="0.5" color_name="blue">
		<cylinder radius="0.15" length="0.05"/>
        <inertia ixx="0.0029167" iyy="0.0029167" izz="0.0056250" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>
	<!-- 前方キャスター -->
	<xacro:link_generator name="caster_forward" mass="0.5" color_name="green">
		<sphere radius="0.05"/>
        <inertia ixx="3.000e-4" iyy="3.000e-4" izz="3.000e-4" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>
	<!-- 後方キャスター -->
	<xacro:link_generator name="caster_backward" mass="0.5" color_name="black">
		<sphere radius="0.05"/>
        <inertia ixx="3.000e-4" iyy="3.000e-4" izz="3.000e-4" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>
	<!-- LiDAR台 -->
	<xacro:link_generator name="lidar_base" mass="0.15" color_name="yellow">
		<box size="0.1 0.1 0.1"/>
		<inertia ixx="0.25" iyy="0.25" izz="0.25" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>
	<!-- LiDAR -->
	<xacro:link_generator name="lidar_link" mass="0.05" color_name="purple">
		<cylinder radius="0.05" length="0.05"/>
		<inertia ixx="0.125" iyy="0.125" izz="0.188" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>

	<!-- ############## ジョイントの生成 ############### -->
	<!-- ベース・ボディ -->
	<xacro:fixed_joint name="base_joint" parent="base_link" child="body">
        <origin xyz="0 0 0.15" rpy="0 0 0"/>
	</xacro:fixed_joint>
	<!-- ボディ・左車輪 -->
	<xacro:continuous_joint name="wheel_left_joint" parent="body" child="wheel_left">
        <origin xyz="0 -0.225 0" rpy="1.57 0 0"/>
        <axis xyz="0 0 1"/>
	</xacro:continuous_joint>
	<!-- ボディ・右車輪 -->
	<xacro:continuous_joint name="wheel_right_joint" parent="body" child="wheel_right">
        <origin xyz="0 0.225 0" rpy="1.57 0 0"/>
        <axis xyz="0 0 1"/>
	</xacro:continuous_joint>
	<!-- ボディ・前方キャスター -->
	<xacro:fixed_joint name="caster_forward_joint" parent="body" child="caster_forward">
        <origin xyz="-0.15 0 -0.1" rpy="0 0 0"/>
	</xacro:fixed_joint>
	<!-- ボディ・後方キャスター -->
	<xacro:fixed_joint name="caster_backward_joint" parent="body" child="caster_backward">
        <origin xyz="0.15 0 -0.1" rpy="0 0 0"/>
	</xacro:fixed_joint>
	<!-- ボディ・LiDAR台 -->
	<xacro:fixed_joint name="lidar_base_joint" parent="body" child="lidar_base">
        <origin xyz="0 0 0.125" rpy="0 0 0"/>
	</xacro:fixed_joint>
	<!-- LiDAR台・LiDAR -->
	<xacro:fixed_joint name="lidar_joint" parent="lidar_base" child="lidar_link">
        <origin xyz="0 0 0.075" rpy="0 0 0"/>
	</xacro:fixed_joint>
</robot>
```

</details>

``joints_macro.xacro``　 ：ジョイントに関するマクロファイル．
``robot_v02.xacro``　　　：3つのマクロファイルで全てのパーツとジョイントを作成するマクロファイル．

#### 確認

```bash:xacroからurdfへ変換
xacro robot_v01.xacro > robot.urdf
```

<details><summary>Gazeboへ反映させるlaunchファイル</summary>

``<arg name="model" default="$(find diff_drive_pkg)/urdf/robot.urdf"/>``
の部分でロードしたいurdfを指定している．

```xml:robot.launch（追加部分）
<launch>

    <!-- 引数 -->
    <arg name="paused" default="false"/>
    <arg name="use_sim_time" default="true"/>
    <arg name="gui" default="true"/>
    <arg name="headless" default="false"/>
    <arg name="debug" default="false"/>
    <arg name="model" default="$(find diff_drive_pkg)/urdf/robot.urdf"/>

    <!-- Gazeboの起動 -->
    <include file="$(find gazebo_ros)/launch/empty_world.launch">
        <arg name="debug" value="$(arg debug)" />
        <arg name="gui" value="$(arg gui)" />
        <arg name="paused" value="$(arg paused)"/>
        <arg name="use_sim_time" value="$(arg use_sim_time)"/>
        <arg name="headless" value="$(arg headless)"/>
    </include>

    <!--ロボットのURDFモデルをパラメータサーバにロードする-->
    <param name = "robot_description" textfile = "$(arg model)"/>

    <!--Gazeboでロボットを生成し，パラメータサーバからのその記述を受ける-->
    <node name = "spawn_urdf" pkg = "gazebo_ros" type = "spawn_model" args = "-param robot_description -urdf -model diff_drive_robot"/>

    <!-- robot_state_publisherの起動 -->
    <node pkg="robot_state_publisher" type="robot_state_publisher"  name="robot_state_publisher">
        <param name="publish_frequency" type="double" value="30.0" />
    </node>
</launch>
```

</details>

![gazebo_without_color.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951300/83ecbb0a-ac03-aeef-20d7-0559e30346f9.png)

右には，VScodeの拡張機能であるURDF previewにより表示させたものである．
左には，Gazeboに読み込んだものを表示している．

### STEP3: Gazebo上での色情報と摩擦を追加
ここでは，各パーツに対してGazebo上で反映できる摩擦係数（クーロン摩擦モデルに関わる）と色情報を記述している．
ただし，各設定の共通部分はマクロとして表現する．


<details><summary>gazebo_material_macro.xacro</summary>

```xml:Xacro
<?xml version="1.0"?>
<robot xmlns:xacro="http://ros.org/wiki/xacro">


<xacro:macro name="gazebo_material" params="ref mu *color">

	<gazebo reference="${ref}">
		<mu1>${mu}</mu1>
		<mu2>${mu}</mu2>
    <xacro:insert_block name="color" />
	</gazebo>

</xacro:macro>

</robot>
```

</details>


<details><summary>robot_v03.xacro</summary>


```xml:Xacro
<?xml version="1.0"?>
<robot xmlns:xacro="http://ros.org/wiki/xacro" name="diff_drive_robot">

	<xacro:include filename="$(find diff_drive_pkg)/xacro/material_colors.xacro" />
	<xacro:include filename="$(find diff_drive_pkg)/xacro/parts_macro.xacro" />
	<xacro:include filename="$(find diff_drive_pkg)/xacro/joints_macro.xacro" />
	<xacro:include filename="$(find diff_drive_pkg)/xacro/gazebo_material_macro.xacro" />

	<!-- ############## リンクの生成 ############### -->
  <link name="base_link"/>
	<!-- ボディ -->
	<xacro:link_generator name="body" mass="1.0" color_name="red">
        <cylinder radius="0.2" length="0.15" />
        <inertia ixx="0.0118750" iyy="0.0118750" izz="0.0200000" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>
	<!-- 左車輪 -->
	<xacro:link_generator name="wheel_left" mass="0.5" color_name="blue">
		<cylinder radius="0.15" length="0.05"/>
        <inertia ixx="0.0029167" iyy="0.0029167" izz="0.0056250" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>
	<!-- 右車輪 -->
	<xacro:link_generator name="wheel_right" mass="0.5" color_name="blue">
		<cylinder radius="0.15" length="0.05"/>
        <inertia ixx="0.0029167" iyy="0.0029167" izz="0.0056250" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>
	<!-- 前方キャスター -->
	<xacro:link_generator name="caster_forward" mass="0.5" color_name="green">
		<sphere radius="0.05"/>
        <inertia ixx="3.000e-4" iyy="3.000e-4" izz="3.000e-4" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>
	<!-- 後方キャスター -->
	<xacro:link_generator name="caster_backward" mass="0.5" color_name="black">
		<sphere radius="0.05"/>
        <inertia ixx="3.000e-4" iyy="3.000e-4" izz="3.000e-4" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>
	<!-- LiDAR台 -->
	<xacro:link_generator name="lidar_base" mass="0.15" color_name="yellow">
		<box size="0.1 0.1 0.1"/>
		<inertia ixx="0.25" iyy="0.25" izz="0.25" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>
	<!-- LiDAR -->
	<xacro:link_generator name="lidar_link" mass="0.05" color_name="purple">
		<cylinder radius="0.05" length="0.05"/>
		<inertia ixx="0.125" iyy="0.125" izz="0.188" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>

	<!-- ############## ジョイントの生成 ############### -->
	<!-- ベース・ボディ -->
	<xacro:fixed_joint name="base_joint" parent="base_link" child="body">
        <origin xyz="0 0 0.15" rpy="0 0 0"/>
	</xacro:fixed_joint>
	<!-- ボディ・左車輪 -->
	<xacro:continuous_joint name="wheel_left_joint" parent="body" child="wheel_left">
        <origin xyz="0 -0.225 0" rpy="1.57 0 0"/>
    <axis xyz="0 0 1"/>
	</xacro:continuous_joint>
	<!-- ボディ・右車輪 -->
	<xacro:continuous_joint name="wheel_right_joint" parent="body" child="wheel_right">
        <origin xyz="0 0.225 0" rpy="1.57 0 0"/>
        <axis xyz="0 0 1"/>
	</xacro:continuous_joint>
	<!-- ボディ・前方キャスター -->
	<xacro:fixed_joint name="caster_forward_joint" parent="body" child="caster_forward">
        <origin xyz="-0.15 0 -0.1" rpy="0 0 0"/>
	</xacro:fixed_joint>
	<!-- ボディ・後方キャスター -->
	<xacro:fixed_joint name="caster_backward_joint" parent="body" child="caster_backward">
        <origin xyz="0.15 0 -0.1" rpy="0 0 0"/>
	</xacro:fixed_joint>
	<!-- ボディ・LiDAR台 -->
	<xacro:fixed_joint name="lidar_base_joint" parent="body" child="lidar_base">
        <origin xyz="0 0 0.125" rpy="0 0 0"/>
	</xacro:fixed_joint>
	<!-- LiDAR台・LiDAR -->
	<xacro:fixed_joint name="lidar_joint" parent="lidar_base" child="lidar_link">
        <origin xyz="0 0 0.075" rpy="0 0 0"/>
	</xacro:fixed_joint>

	<!-- ############## Gazebo上のパーツ設定 ############### -->

	<xacro:gazebo_material ref="body" mu="0.2">
		<material>Gazebo/Red</material>
	</xacro:gazebo_material>
	<xacro:gazebo_material ref="wheel_left" mu="0.2">
		<material>Gazebo/Blue</material>
	</xacro:gazebo_material>
	<xacro:gazebo_material ref="wheel_right" mu="0.2">
		<material>Gazebo/Blue</material>
	</xacro:gazebo_material>
	<xacro:gazebo_material ref="caster_forward" mu="0.0">
		<material>Gazebo/Green</material>
	</xacro:gazebo_material>
	<xacro:gazebo_material ref="caster_backward" mu="0.0">
		<material>Gazebo/Black</material>
	</xacro:gazebo_material>
	<xacro:gazebo_material ref="lidar_base" mu="0.0">
		<material>Gazebo/Yellow</material>
	</xacro:gazebo_material>
	<xacro:gazebo_material ref="lidar_link" mu="0.0">
		<material>Gazebo/Purple</material>
	</xacro:gazebo_material>

</robot>
```

</details>


``gazebo_material_macro.xacro``　 ：Gazeboのマテリアルに関するマクロファイル．
``robot_v03.xacro``　　　　　　　　：4つのマクロファイルで全てのパーツとジョイントおよびGazeboのマテリアルを作成するマクロファイル．


![gazebo_colored.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951300/6b63ca66-129a-6c9b-98fd-24126efac0d7.png)
いい感じに色付けができた．


### STEP4: 差動駆動プラグインの追加
ここでは，差動駆動させるための設定をおこなう．
ただし，マクロとして表現する．

<details><summary>gazebo_diffJoint_macro.xacro</summary>

```xml:Xacro
<?xml version="1.0"?>
<robot xmlns:xacro="http://ros.org/wiki/xacro">


<xacro:macro name="gazebo_diff_Joint" params="leftJoint_name rightJoint_name base_name tread wheel_Diameter">

  <gazebo>
    <!--差動駆動プラグインを指定-->
    <plugin name="differential_drive_controller" filename="libgazebo_ros_diff_drive.so">
      <!--left_wheel_jointとright_wheel_jointをそれぞれ左関節右関節に指定-->
      <leftJoint>${leftJoint_name}</leftJoint>
      <rightJoint>${rightJoint_name}</rightJoint>
      <!--台座であるbase_linkをrobotBaseFrameに指定-->
      <robotBaseFrame>${base_name}</robotBaseFrame>
      <!--トレッドを0.25m，車輪直径0.07mとする-->
      <wheelSeparation>${tread}</wheelSeparation>
      <wheelDiameter>${wheel_Diameter}</wheelDiameter>
      <!--車輪の状態を配信する設定にする-->
      <publishWheelJointState>true</publishWheelJointState>
    </plugin>
  </gazebo>

</xacro:macro>


</robot>
```

</details>


<details><summary>robot_v04.xacro</summary>


```xml:Xacro
<?xml version="1.0"?>
<robot xmlns:xacro="http://ros.org/wiki/xacro" name="diff_drive_robot">

	<xacro:include filename="$(find diff_drive_pkg)/xacro/material_colors.xacro" />
	<xacro:include filename="$(find diff_drive_pkg)/xacro/parts_macro.xacro" />
	<xacro:include filename="$(find diff_drive_pkg)/xacro/joints_macro.xacro" />
	<xacro:include filename="$(find diff_drive_pkg)/xacro/gazebo_material_macro.xacro" />
	<xacro:include filename="$(find diff_drive_pkg)/xacro/gazebo_diffJoint_macro.xacro" />

	<!-- ############## リンクの生成 ############### -->
  <link name="base_link"/>
	<!-- ボディ -->
	<xacro:link_generator name="body" mass="1.0" color_name="red">
        <cylinder radius="0.2" length="0.15" />
        <inertia ixx="0.0118750" iyy="0.0118750" izz="0.0200000" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>
	<!-- 左車輪 -->
	<xacro:link_generator name="wheel_left" mass="0.5" color_name="blue">
		<cylinder radius="0.15" length="0.05"/>
        <inertia ixx="0.0029167" iyy="0.0029167" izz="0.0056250" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>
	<!-- 右車輪 -->
	<xacro:link_generator name="wheel_right" mass="0.5" color_name="blue">
		<cylinder radius="0.15" length="0.05"/>
        <inertia ixx="0.0029167" iyy="0.0029167" izz="0.0056250" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>
	<!-- 前方キャスター -->
	<xacro:link_generator name="caster_forward" mass="0.5" color_name="green">
		<sphere radius="0.05"/>
        <inertia ixx="3.000e-4" iyy="3.000e-4" izz="3.000e-4" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>
	<!-- 後方キャスター -->
	<xacro:link_generator name="caster_backward" mass="0.5" color_name="black">
		<sphere radius="0.05"/>
        <inertia ixx="3.000e-4" iyy="3.000e-4" izz="3.000e-4" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>
	<!-- LiDAR台 -->
	<xacro:link_generator name="lidar_base" mass="0.15" color_name="yellow">
		<box size="0.1 0.1 0.1"/>
		<inertia ixx="0.25" iyy="0.25" izz="0.25" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>
	<!-- LiDAR -->
	<xacro:link_generator name="lidar_link" mass="0.05" color_name="purple">
		<cylinder radius="0.05" length="0.05"/>
		<inertia ixx="0.125" iyy="0.125" izz="0.188" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>

	<!-- ############## ジョイントの生成 ############### -->
	<!-- ベース・ボディ -->
	<xacro:fixed_joint name="base_joint" parent="base_link" child="body">
        <origin xyz="0 0 0.15" rpy="0 0 0"/>
	</xacro:fixed_joint>
	<!-- ボディ・左車輪 -->
	<xacro:continuous_joint name="wheel_left_joint" parent="body" child="wheel_left">
        <origin xyz="0 -0.225 0" rpy="1.57 0 0"/>
        <axis xyz="0 0 1"/>
	</xacro:continuous_joint>
	<!-- ボディ・右車輪 -->
	<xacro:continuous_joint name="wheel_right_joint" parent="body" child="wheel_right">
        <origin xyz="0 0.225 0" rpy="1.57 0 0"/>
        <axis xyz="0 0 1"/>
	</xacro:continuous_joint>
	<!-- ボディ・前方キャスター -->
	<xacro:fixed_joint name="caster_forward_joint" parent="body" child="caster_forward">
        <origin xyz="-0.15 0 -0.1" rpy="0 0 0"/>
	</xacro:fixed_joint>
	<!-- ボディ・後方キャスター -->
	<xacro:fixed_joint name="caster_backward_joint" parent="body" child="caster_backward">
        <origin xyz="0.15 0 -0.1" rpy="0 0 0"/>
	</xacro:fixed_joint>
	<!-- ボディ・LiDAR台 -->
	<xacro:fixed_joint name="lidar_base_joint" parent="body" child="lidar_base">
        <origin xyz="0 0 0.125" rpy="0 0 0"/>
	</xacro:fixed_joint>
	<!-- LiDAR台・LiDAR -->
	<xacro:fixed_joint name="lidar_joint" parent="lidar_base" child="lidar_link">
        <origin xyz="0 0 0.075" rpy="0 0 0"/>
	</xacro:fixed_joint>

	<!-- ############## Gazebo上のパーツ設定 ############### -->
	<xacro:gazebo_material ref="body" mu="0.2">
		<material>Gazebo/Red</material>
	</xacro:gazebo_material>
	<xacro:gazebo_material ref="wheel_left" mu="0.2">
		<material>Gazebo/Blue</material>
	</xacro:gazebo_material>
	<xacro:gazebo_material ref="wheel_right" mu="0.2">
		<material>Gazebo/Blue</material>
	</xacro:gazebo_material>
	<xacro:gazebo_material ref="caster_forward" mu="0.0">
		<material>Gazebo/Green</material>
	</xacro:gazebo_material>
	<xacro:gazebo_material ref="caster_backward" mu="0.0">
		<material>Gazebo/Black</material>
	</xacro:gazebo_material>
	<xacro:gazebo_material ref="lidar_base" mu="0.0">
		<material>Gazebo/Yellow</material>
	</xacro:gazebo_material>
	<xacro:gazebo_material ref="lidar_link" mu="0.0">
		<material>Gazebo/Purple</material>
	</xacro:gazebo_material>

	<!-- ############## Gazebo上の差動駆動設定 ############### -->
	<xacro:gazebo_diff_Joint leftJoint_name="wheel_left_joint" rightJoint_name="wheel_right_joint" base_name="base_link" tread="0.45" wheel_Diameter="0.30"/>

</robot>
```

</details>


``gazebo_diffJoint_macro.xacro``：Gazeboの差動駆動プラグインに関するマクロファイル．
``robot_v04.xacro``　　　　　　　：5つのマクロファイルで全てのパーツとジョイント，Gazeboのマテリアルおよび差動駆動を作成するマクロファイル．

### STEP5: LiDARの追加
ここでは，センサを追加するための設定を記述する．
今回はセンサとしてLiDARを模擬する．LiDARを模擬するにあたって，
Gazeboのプラグインを利用する．

<details><summary>gazebo_LiDAR_macro.xacro</summary>

```xml:Xacro
<?xml version="1.0"?>
<robot xmlns:xacro="http://ros.org/wiki/xacro">


<xacro:macro  name="gazebo_LiDAR" 
              params="ref sensor_name viz update_rate sample_N
                      scan_resolution min_angle max_angle 
                      min_range max_range range_resolution
                      plugIn_name topic_name frame_name *pose">
  <!-- GPU rayというタイプで作成 -->
  <gazebo reference="${ref}">
    <sensor type="gpu_ray" name="${sensor_name}">
      <xacro:insert_block name="pose" />
      <visualize>${viz}</visualize>
      <update_rate>${update_rate}</update_rate>
      <ray>
        <scan>
          <horizontal>
            <samples>${sample_N}</samples>
            <resolution>${scan_resolution}</resolution>
            <min_angle>${min_angle}</min_angle>
            <max_angle>${max_angle}</max_angle>
          </horizontal>
        </scan>
        <range>
          <min>${min_range}</min>
          <max>${max_range}</max>
          <resolution>${range_resolution}</resolution>
        </range>
        <noise>
          <type>gaussian</type>
          <!-- Noise parameters based on published spec for Hokuyo laser
               achieving "+-30mm" accuracy at range < 10m.  A mean of 0.0m and
               stddev of 0.01m will put 99.7% of samples within 0.03m of the true
               reading. -->
          <mean>0.0</mean>
          <stddev>0.01</stddev>
        </noise>
      </ray>
      <plugin name="${plugIn_name}" filename="libgazebo_ros_gpu_laser.so">
        <topicName>${topic_name}</topicName>
        <frameName>${frame_name}</frameName>
      </plugin>
    </sensor>
  </gazebo>
</xacro:macro>

</robot>
```

</details>



<details><summary>robot_v05.xacro</summary>


```xml:Xacro
<?xml version="1.0"?>
<robot xmlns:xacro="http://ros.org/wiki/xacro" name="diff_drive_robot">

	<xacro:include filename="$(find diff_drive_pkg)/xacro/v04_add_gazebo_LiDAR/material_colors.xacro" />
	<xacro:include filename="$(find diff_drive_pkg)/xacro/v04_add_gazebo_LiDAR/parts_macro.xacro" />
	<xacro:include filename="$(find diff_drive_pkg)/xacro/v04_add_gazebo_LiDAR/joints_macro.xacro" />
	<xacro:include filename="$(find diff_drive_pkg)/xacro/v04_add_gazebo_LiDAR/gazebo_material_macro.xacro" />
	<xacro:include filename="$(find diff_drive_pkg)/xacro/v04_add_gazebo_LiDAR/gazebo_diffJoint_macro.xacro" />
	<xacro:include filename="$(find diff_drive_pkg)/xacro/v04_add_gazebo_LiDAR/gazebo_LiDAR_macro.xacro" />

	<!-- ############## リンクの生成 ############### -->
  <link name="base_link"/>
	<!-- ボディ -->
	<xacro:link_generator name="body" mass="1.0" color_name="red">
        <cylinder radius="0.2" length="0.15" />
        <inertia ixx="0.0118750" iyy="0.0118750" izz="0.0200000" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>
	<!-- 左車輪 -->
	<xacro:link_generator name="wheel_left" mass="0.5" color_name="blue">
		<cylinder radius="0.15" length="0.05"/>
        <inertia ixx="0.0029167" iyy="0.0029167" izz="0.0056250" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>
	<!-- 右車輪 -->
	<xacro:link_generator name="wheel_right" mass="0.5" color_name="blue">
		<cylinder radius="0.15" length="0.05"/>
        <inertia ixx="0.0029167" iyy="0.0029167" izz="0.0056250" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>
	<!-- 前方キャスター -->
	<xacro:link_generator name="caster_forward" mass="0.5" color_name="green">
		<sphere radius="0.05"/>
        <inertia ixx="3.000e-4" iyy="3.000e-4" izz="3.000e-4" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>
	<!-- 後方キャスター -->
	<xacro:link_generator name="caster_backward" mass="0.5" color_name="black">
		<sphere radius="0.05"/>
        <inertia ixx="3.000e-4" iyy="3.000e-4" izz="3.000e-4" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>
	<!-- LiDAR台 -->
	<xacro:link_generator name="lidar_base" mass="0.15" color_name="yellow">
		<box size="0.1 0.1 0.1"/>
		<inertia ixx="0.25" iyy="0.25" izz="0.25" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>
	<!-- LiDAR -->
	<xacro:link_generator name="lidar_link" mass="0.05" color_name="purple">
		<cylinder radius="0.05" length="0.05"/>
		<inertia ixx="0.125" iyy="0.125" izz="0.188" ixy="0" ixz="0" iyz="0"/>
	</xacro:link_generator>

	<!-- ############## ジョイントの生成 ############### -->
	<!-- ベース・ボディ -->
	<xacro:fixed_joint name="base_joint" parent="base_link" child="body">
        <origin xyz="0 0 0.15" rpy="0 0 0"/>
	</xacro:fixed_joint>
	<!-- ボディ・左車輪 -->
	<xacro:continuous_joint name="wheel_left_joint" parent="body" child="wheel_left">
        <origin xyz="0 -0.225 0" rpy="1.57 0 0"/>
        <axis xyz="0 0 1"/>
	</xacro:continuous_joint>
	<!-- ボディ・右車輪 -->
	<xacro:continuous_joint name="wheel_right_joint" parent="body" child="wheel_right">
        <origin xyz="0 0.225 0" rpy="1.57 0 0"/>
        <axis xyz="0 0 1"/>
	</xacro:continuous_joint>
	<!-- ボディ・前方キャスター -->
	<xacro:fixed_joint name="caster_forward_joint" parent="body" child="caster_forward">
        <origin xyz="-0.15 0 -0.1" rpy="0 0 0"/>
	</xacro:fixed_joint>
	<!-- ボディ・後方キャスター -->
	<xacro:fixed_joint name="caster_backward_joint" parent="body" child="caster_backward">
        <origin xyz="0.15 0 -0.1" rpy="0 0 0"/>
	</xacro:fixed_joint>
	<!-- ボディ・LiDAR台 -->
	<xacro:fixed_joint name="lidar_base_joint" parent="body" child="lidar_base">
        <origin xyz="0 0 0.125" rpy="0 0 0"/>
	</xacro:fixed_joint>
	<!-- LiDAR台・LiDAR -->
	<xacro:fixed_joint name="lidar_joint" parent="lidar_base" child="lidar_link">
        <origin xyz="0 0 0.075" rpy="0 0 0"/>
	</xacro:fixed_joint>

	<!-- ############## Gazebo上のパーツ設定 ############### -->
	<xacro:gazebo_material ref="body" mu="0.2">
		<material>Gazebo/Red</material>
	</xacro:gazebo_material>
	<xacro:gazebo_material ref="wheel_left" mu="0.2">
		<material>Gazebo/Blue</material>
	</xacro:gazebo_material>
	<xacro:gazebo_material ref="wheel_right" mu="0.2">
		<material>Gazebo/Blue</material>
	</xacro:gazebo_material>
	<xacro:gazebo_material ref="caster_forward" mu="0.0">
		<material>Gazebo/Green</material>
	</xacro:gazebo_material>
	<xacro:gazebo_material ref="caster_backward" mu="0.0">
		<material>Gazebo/Black</material>
	</xacro:gazebo_material>
	<xacro:gazebo_material ref="lidar_base" mu="0.0">
		<material>Gazebo/Yellow</material>
	</xacro:gazebo_material>
	<xacro:gazebo_material ref="lidar_link" mu="0.0">
		<material>Gazebo/Purple</material>
	</xacro:gazebo_material>

	<!-- ############## Gazebo上の差動駆動設定 ############### -->
	<xacro:gazebo_diff_Joint leftJoint_name="wheel_left_joint" rightJoint_name="wheel_right_joint" base_name="base_link" tread="0.45" wheel_Diameter="0.30"/>

	<!-- ############## Gazebo上のLiDAR設定 ############### -->
	<xacro:gazebo_LiDAR 
		ref="lidar_link" 
		sensor_name="ydlidar_sensor" 
		viz="true" 
		update_rate="40"
		sample_N="700" 
		scan_resolution="1"
		min_angle="-3.14159265358979"
		max_angle="3.14159265358979"
		min_range="0.12"
		max_range="8"
		range_resolution="0.72"
		plugIn_name="gazebo_ros_ydlidar_controller"
		topic_name="/scan"
		frame_name="lidar_link"
																		>
		<pose>0 0 0 0 0 0</pose>
	</xacro:gazebo_LiDAR>
	
</robot>
```

</details>

``gazebo_LiDAR_macro.xacro``　　：GazeboのLiDARプラグインに関するマクロファイル．
``robot_v04.xacro``　　　　　　　：6つのマクロファイルで全てのパーツとジョイント，Gazeboのマテリアル，差動駆動およびLiDARを作成するマクロファイル．

#### 確認

これでXacroは完成である．
ここで，Gazebo, Rvizで確認したい．

```bash:xacroからurdfへ変換
xacro robot_v05.xacro > robot_v05.urdf
```

<details><summary>robot_LRF.launch</summary>

```xml:robot_LRF.launch
<launch>

    <!-- 引数 -->
    <arg name="paused" default="false"/>
    <arg name="use_sim_time" default="true"/>
    <arg name="gui" default="true"/>
    <arg name="headless" default="false"/>
    <arg name="debug" default="false"/>
    <arg name="model" default="$(find diff_drive_pkg)/urdf/robot_v05.urdf"/>
    <!-- <arg name="model" default="$(find diff_drive_pkg)/urdf/robot_with_lidar.urdf"/> -->
    <arg name="x" default="2.0"/>
    <arg name="y" default="0"/>
    <arg name="z" default="0"/>

    <!-- Gazeboの起動 -->
    <include file="$(find gazebo_ros)/launch/empty_world.launch">
        <arg name="world_name" value="$(find turtlebot3_gazebo)/worlds/turtlebot3_world.world"/>
        <arg name="debug" value="$(arg debug)" />
        <arg name="gui" value="$(arg gui)" />
        <arg name="paused" value="$(arg paused)"/>
        <arg name="use_sim_time" value="$(arg use_sim_time)"/>
        <arg name="headless" value="$(arg headless)"/>
    </include>

    <!--ロボットのURDFモデルをパラメータサーバにロードする-->
    <param name = "robot_description" textfile = "$(arg model)"/>

    <!--Gazeboでロボットを生成し，パラメータサーバからのその記述を受ける-->
    <node name = "spawn_urdf" pkg = "gazebo_ros" type = "spawn_model" args = "-param robot_description -urdf -model diff_drive_robot -x $(arg x) -y $(arg y) -z $(arg z)"/>

    <!-- robot_state_publisherの起動 -->
    <node pkg="robot_state_publisher" type="robot_state_publisher"  name="robot_state_publisher">
        <param name="publish_frequency" type="double" value="30.0" />
    </node>

    <!-- Rvizを起動 -->
    <node name="rviz" pkg="rviz" type="rviz" args="-d $(find diff_drive_pkg)/rviz/robot.rviz"/>
</launch>
```

</details>

注意）Rvizの設定を保存したrvizファイルはあるものとしている．


<details><summary>本記事でのrvizファイル</summary>

```yaml:robot.rviz
Panels:
  - Class: rviz/Displays
    Help Height: 85
    Name: Displays
    Property Tree Widget:
      Expanded:
        - /Global Options1
        - /Status1
      Splitter Ratio: 0.5
    Tree Height: 674
  - Class: rviz/Selection
    Name: Selection
  - Class: rviz/Tool Properties
    Expanded:
      - /2D Pose Estimate1
      - /2D Nav Goal1
      - /Publish Point1
    Name: Tool Properties
    Splitter Ratio: 0.5886790156364441
  - Class: rviz/Views
    Expanded:
      - /Current View1
    Name: Views
    Splitter Ratio: 0.5
  - Class: rviz/Time
    Name: Time
    SyncMode: 0
    SyncSource: LaserScan
Preferences:
  PromptSaveOnExit: true
Toolbars:
  toolButtonStyle: 2
Visualization Manager:
  Class: ""
  Displays:
    - Alpha: 0.5
      Cell Size: 1
      Class: rviz/Grid
      Color: 160; 160; 164
      Enabled: true
      Line Style:
        Line Width: 0.029999999329447746
        Value: Lines
      Name: Grid
      Normal Cell Count: 0
      Offset:
        X: 0
        Y: 0
        Z: 0
      Plane: XY
      Plane Cell Count: 10
      Reference Frame: <Fixed Frame>
      Value: true
    - Alpha: 1
      Autocompute Intensity Bounds: true
      Autocompute Value Bounds:
        Max Value: 10
        Min Value: -10
        Value: true
      Axis: Z
      Channel Name: intensity
      Class: rviz/LaserScan
      Color: 255; 255; 255
      Color Transformer: Intensity
      Decay Time: 0
      Enabled: true
      Invert Rainbow: false
      Max Color: 255; 255; 255
      Min Color: 0; 0; 0
      Name: LaserScan
      Position Transformer: XYZ
      Queue Size: 10
      Selectable: true
      Size (Pixels): 3
      Size (m): 0.05000000074505806
      Style: Flat Squares
      Topic: /scan
      Unreliable: false
      Use Fixed Frame: true
      Use rainbow: true
      Value: true
    - Alpha: 1
      Class: rviz/RobotModel
      Collision Enabled: false
      Enabled: true
      Links:
        All Links Enabled: true
        Expand Joint Details: false
        Expand Link Details: false
        Expand Tree: false
        Link Tree Style: Links in Alphabetic Order
        base_link:
          Alpha: 1
          Show Axes: false
          Show Trail: false
        body:
          Alpha: 1
          Show Axes: false
          Show Trail: false
          Value: true
        caster_backward:
          Alpha: 1
          Show Axes: false
          Show Trail: false
          Value: true
        caster_forward:
          Alpha: 1
          Show Axes: false
          Show Trail: false
          Value: true
        lidar_base:
          Alpha: 1
          Show Axes: false
          Show Trail: false
          Value: true
        lidar_link:
          Alpha: 1
          Show Axes: false
          Show Trail: false
          Value: true
        wheel_left:
          Alpha: 1
          Show Axes: false
          Show Trail: false
          Value: true
        wheel_right:
          Alpha: 1
          Show Axes: false
          Show Trail: false
          Value: true
      Name: RobotModel
      Robot Description: robot_description
      TF Prefix: ""
      Update Interval: 0
      Value: true
      Visual Enabled: true
    - Class: rviz/TF
      Enabled: true
      Frame Timeout: 15
      Frames:
        All Enabled: true
        base_link:
          Value: true
        body:
          Value: true
        caster_backward:
          Value: true
        caster_forward:
          Value: true
        lidar_base:
          Value: true
        lidar_link:
          Value: true
        odom:
          Value: true
        wheel_left:
          Value: true
        wheel_right:
          Value: true
      Marker Alpha: 1
      Marker Scale: 1
      Name: TF
      Show Arrows: true
      Show Axes: true
      Show Names: true
      Tree:
        odom:
          base_link:
            body:
              caster_backward:
                {}
              caster_forward:
                {}
              lidar_base:
                lidar_link:
                  {}
              wheel_left:
                {}
              wheel_right:
                {}
      Update Interval: 0
      Value: true
  Enabled: true
  Global Options:
    Background Color: 48; 48; 48
    Default Light: true
    Fixed Frame: odom
    Frame Rate: 30
  Name: root
  Tools:
    - Class: rviz/Interact
      Hide Inactive Objects: true
    - Class: rviz/MoveCamera
    - Class: rviz/Select
    - Class: rviz/FocusCamera
    - Class: rviz/Measure
    - Class: rviz/SetInitialPose
      Theta std deviation: 0.2617993950843811
      Topic: /initialpose
      X std deviation: 0.5
      Y std deviation: 0.5
    - Class: rviz/SetGoal
      Topic: /move_base_simple/goal
    - Class: rviz/PublishPoint
      Single click: true
      Topic: /clicked_point
  Value: true
  Views:
    Current:
      Class: rviz/Orbit
      Distance: 9.972949981689453
      Enable Stereo Rendering:
        Stereo Eye Separation: 0.05999999865889549
        Stereo Focal Distance: 1
        Swap Stereo Eyes: false
        Value: false
      Field of View: 0.7853981852531433
      Focal Point:
        X: 0
        Y: 0
        Z: 0
      Focal Shape Fixed Size: true
      Focal Shape Size: 0.05000000074505806
      Invert Z Axis: false
      Name: Current View
      Near Clip Distance: 0.009999999776482582
      Pitch: 0.9503982067108154
      Target Frame: <Fixed Frame>
      Yaw: 0.01539910864084959
    Saved: ~
Window Geometry:
  Displays:
    collapsed: false
  Height: 991
  Hide Left Dock: false
  Hide Right Dock: true
  QMainWindow State: 000000ff00000000fd00000004000000000000015a00000338fc0200000008fb0000001200530065006c0065006300740069006f006e00000001e10000009b0000006b00fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000004400000338000000eb00fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261000000010000010f00000338fc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073000000004400000338000000b900fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000004090000003efc0100000002fb0000000800540069006d0065010000000000000409000003a200fffffffb0000000800540069006d00650100000000000004500000000000000000000002a80000033800000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000
  Selection:
    collapsed: false
  Time:
    collapsed: false
  Tool Properties:
    collapsed: false
  Views:
    collapsed: true
  Width: 1033
  X: 9
  Y: 38

```

</details>

![gazebo_with_Rviz.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951300/250f9f34-6e81-93a0-24e4-2843297ec9a4.png)

Gazebo上で見えている青色はLiDARで使用されているレーザを可視化したものである．

<details><summary>このときに見られるトピック一覧</summary>

```bash:rostopic list
/clicked_point
/clock
/cmd_vel
/gazebo/link_states
/gazebo/model_states
/gazebo/parameter_descriptions
/gazebo/parameter_updates
/gazebo/performance_metrics
/gazebo/set_link_state
/gazebo/set_model_state
/initialpose
/joint_states
/move_base_simple/goal
/odom
/rosout
/rosout_agg
/scan
/tf
/tf_static
```

</details>

/cmd_velがあり，そのトピックにメッセージを配信すれば，動かせる．

## URDFとの比較（短縮化）
![shorten_code.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951300/e21f531e-8aa9-a0fe-3cb3-303f5bdd7235.png)

URDFで書いていた時には300行近くあったものが，Xacroでは130行ほどになった．
短くなっただけでなく，マクロや変数を使っての表現になったため，見やすさと後の変更への対応のしやすさが向上している．

## 実験

「/cmd_velがあり，そのトピックにメッセージを配信すれば，動かせる．」
ということなので，turtlebot3_teleopパッケージのノードを使わせていただくこととする．

<details><summary>robot_LRF_Move.launch</summary>

```xml:robot_LRF_Move.launch
<launch>

    <!-- 引数 -->
    <arg name="paused" default="false"/>
    <arg name="use_sim_time" default="true"/>
    <arg name="gui" default="true"/>
    <arg name="headless" default="false"/>
    <arg name="debug" default="false"/>
    <arg name="model" default="$(find diff_drive_pkg)/urdf/robot_v05.urdf"/>
    <!-- <arg name="model" default="$(find diff_drive_pkg)/urdf/robot_with_lidar.urdf"/> -->
    <arg name="x" default="2.0"/>
    <arg name="y" default="0"/>
    <arg name="z" default="0"/>

    <!-- Gazeboの起動 -->
    <include file="$(find gazebo_ros)/launch/empty_world.launch">
        <arg name="world_name" value="$(find turtlebot3_gazebo)/worlds/turtlebot3_world.world"/>
        <arg name="debug" value="$(arg debug)" />
        <arg name="gui" value="$(arg gui)" />
        <arg name="paused" value="$(arg paused)"/>
        <arg name="use_sim_time" value="$(arg use_sim_time)"/>
        <arg name="headless" value="$(arg headless)"/>
    </include>

    <!--ロボットのURDFモデルをパラメータサーバにロードする-->
    <param name = "robot_description" textfile = "$(arg model)"/>

    <!--GazeboでTortoiseBotを生成し，パラメータサーバからのその記述を受ける-->
    <node name = "spawn_urdf" pkg = "gazebo_ros" type = "spawn_model" args = "-param robot_description -urdf -model diff_drive_robot -x $(arg x) -y $(arg y) -z $(arg z)"/>

    <!-- robot_state_publisherの起動 -->
    <node pkg="robot_state_publisher" type="robot_state_publisher"  name="robot_state_publisher">
        <param name="publish_frequency" type="double" value="30.0" />
    </node>

    <!-- Rvizを起動 -->
    <node name="rviz" pkg="rviz" type="rviz" args="-d $(find diff_drive_pkg)/rviz/robot.rviz"/>

    <!-- teleop nodeを起動 -->
    <node name="teleop" pkg="turtlebot3_teleop" type="turtlebot3_teleop_key" output="screen" />

</launch>
```

</details>

<iframe width="560" height="315" src="https://www.youtube.com/embed/1mSPaBToboA" title="" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

今はいくつかの設定をしていないことによるWarningがあるが，とりあえず無視して実験している．
見づらい場合は，別ターミナルでteleopだけ起動させることもできる．
PCのスペックのためか少し動作が遅いため，動画は16倍速にしている．



## 感想
今回でようやくXacroを使ってURDFの体系化をおこなうことができた．Xacro自体もしっかりと理解して使うのは初めてであり，マクロを別ファイルで定義してXacroの中でXacroを呼び出すことができるのも知らなかった．Xacroによる体系化はロボットモデルをスクリプトで表現する際の頭の整理にもなった．

ここまでくれば，あとは自分の好きなものを作るだけとなる．
今回はLiDARだけのセンサにしたが，カメラなんかも搭載していくと面白そうである．


## 参考文献
https://wiki.ros.org/urdf/Tutorials/Using%20Xacro%20to%20Clean%20Up%20a%20URDF%20File

https://qiita.com/Yuya-Shimizu/items/1fd238211ed35d187e10

https://qiita.com/Yuya-Shimizu/items/cd48dd6af6839aa2764c