ROSの勉強　第46弾：URDF: ロボットモデルの構築をマスター

# #プログラミング ROS< URDF: ロボットモデルの構築をマスター >

## はじめに
ROS(Robot Operating System)をさらに扱えるようになることが目的である．その第46弾として，「URDF: ロボットモデルの構築をマスター」を扱う．

## 環境
##### 仮想環境
|||
|:-:|:--|
|ソフト|VMware Workstation 15|
|実装RAM|3 GB|
|OS|Ubuntu 64 ビット|
|isoファイル|ubuntu-ja-18.04.3-desktop-amd64.iso|

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

##### ROS
|||
|:-:|:--|
|Distribution|melodic|

##URDFについて
URDFについては，@srsさんの記事に十分まとめられているため，以下の記事を紹介するだけにする．

https://qiita.com/srs/items/35bbaadd6c4be1e39bb9

ここでは，URDFにおいて，自分の思いどおりにロボットモデルの構造を作ることができるように実践しながら，要点をおさえる．

## ロボットモデルの構築
### パーツの作成
ロボットモデルに機能だけを持たせるだけの場合必要ないかもしれないが，やはりせっかくロボットモデルを作成するなら，見た目やジオメトリまで本物のロボットに近づけたいという思いがある．

そこで，必要となるのが3Dモデルである．

今回は，3リンクロボット（linkbotと呼ぶ）を作ってみた．
##### 設計
![画像2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951300/674a7048-dfc9-5e06-1e4a-d2251bd8c323.png)

##### 3Dモデルの作成（by Inventor）
![画像3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951300/85ea5959-c8b3-5228-6520-2fc9d4d7df92.png)
注意すべきことは，単位を$m$にしておくこと．（URDFでの単位がSI単位系であるため．）　

ここで，URDFで使うためにCAD形式に出力しておく．（ここでは**stlファイル**に書き出し．この時も書き出し設定が$m$単位になっていることを確認）
ただし，ここでは，3つのパーツごとに出力している．

##### 原点設定
出力したstlにおいて，原点はその設計したときの原点となってしまっている．設計の段階で，気を付けてもよいが，それは面倒であるため作成後，新たに原点を望みの位置に設定する．ここでは，結果的に以下のような状態にしたい．
![画像4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951300/d63086df-7421-36b1-8c48-da2ade26f4b2.png)
ここで，parentとchildの関係について示しておく．
![画像1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951300/35267048-137e-4a89-4afb-f051512e5c34.png)
**parentの原点からchild原点までの距離**：パーツ間の位置を決めるに必要
**childの原点**：jointの原点

ここでは，blenderを使って原点を設定した．それを改めて出力する．

### パーツの組み合わせ

<details><summary>URDF完成形</summary>

```xml:URDF
<?xml version="1.0" encoding="utf-8"?>
<!-- =================================================================================== -->
<!-- |    This document was autogenerated by xacro from fall_sim_001/urdf/linkbot.xacro | -->
<!-- |    EDITING THIS FILE BY HAND IS NOT RECOMMENDED                                 | -->
<!-- =================================================================================== -->
<robot name="linkbot">
  <link name="base_link"/>
  <!-- link名 -->
  <link name="side_link_001">
    <!-- 見た目 -->
    <visual>
      <geometry>
        <mesh filename="package://fall_sim_001/mesh/side_link.stl"/>
      </geometry>
      <material name="red">
        <color rgba="0.7 0.0 0.0 1.0"/>
      </material>
      <origin rpy="0 0 0" xyz="0 0 0"/>
    </visual>
    <!--物理的特性-->
    <!--干渉-->
    <collision>
      <geometry>
        <mesh filename="package://fall_sim_001/mesh/side_link.stl"/>
      </geometry>
    </collision>
    <!--慣性-->
    <inertial>
      <mass value="0.1202"/>
      <inertia ixx="0.00011064095826" ixy="0" ixz="0" iyy="0.00010319975843" iyz="0" izz="9.3613347187e-06"/>
    </inertial>
  </link>
  <!-- link名 -->
  <link name="side_link_002">
    <!-- 見た目 -->
    <visual>
      <geometry>
        <mesh filename="package://fall_sim_001/mesh/side_link.stl"/>
      </geometry>
      <material name="red">
        <color rgba="0.7 0.0 0.0 1.0"/>
      </material>
      <origin rpy="0 0 0" xyz="0 0 0"/>
    </visual>
    <!--物理的特性-->
    <!--干渉-->
    <collision>
      <geometry>
        <mesh filename="package://fall_sim_001/mesh/side_link.stl"/>
      </geometry>
    </collision>
    <!--慣性-->
    <inertial>
      <mass value="0.1202"/>
      <inertia ixx="0.00011064095826" ixy="0" ixz="0" iyy="0.00010319975843" iyz="0" izz="9.3613347187e-06"/>
    </inertial>
  </link>
  <!-- link名 -->
  <link name="center_link">
    <!-- 見た目 -->
    <visual>
      <geometry>
        <mesh filename="package://fall_sim_001/mesh/center_link.stl"/>
      </geometry>
      <material name="silver">
        <color rgba="0.5 0.5 0.5 1.0"/>
      </material>
      <origin rpy="0 0 0" xyz="0 0 0"/>
    </visual>
    <!--物理的特性-->
    <!--干渉-->
    <collision>
      <geometry>
        <mesh filename="package://fall_sim_001/mesh/center_link.stl"/>
      </geometry>
    </collision>
    <!--慣性-->
    <inertial>
      <mass value="0.2102"/>
      <inertia ixx="0.00021446607008" ixy="0" ixz="0" iyy="0.0002021844467" iyz="0" izz="1.6086162789e-05"/>
    </inertial>
  </link>
  <joint name="base_joint" type="fixed">
    <parent link="base_link"/>
    <child link="center_link"/>
    <origin rpy="0 0 0" xyz="0.0 0 0"/>
    <limit effort="0" lower="-1.57079632679" upper="1.57079632679" velocity="0"/>
  </joint>
  <joint name="joint_001" type="revolute">
    <parent link="center_link"/>
    <child link="side_link_001"/>
    <axis xyz="0 1 0"/>
    <origin rpy="0 3.14159265359 0" xyz="-0.056 0 0"/>
    <limit effort="0" lower="-1.57079632679" upper="1.57079632679" velocity="0"/>
  </joint>
  <joint name="joint_002" type="revolute">
    <parent link="center_link"/>
    <child link="side_link_002"/>
    <axis xyz="0 1 0"/>
    <origin rpy="0 0 0" xyz="0.056 0 0"/>
    <limit effort="0" lower="-1.57079632679" upper="1.57079632679" velocity="0"/>
  </joint>
  <transmission name="motor_001">
    <type>transmission_interface/SimpleTransmission</type>
    <!--関節の指定-->
    <joint name="joint_001">
      <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
    </joint>
    <!--アクチュエータの定義（ギア比1の減速機）-->
    <actuator name="trans_001">
      <hardwareInterface>PositionJointInterface</hardwareInterface>
      <mechanicalReduction>1</mechanicalReduction>
    </actuator>
  </transmission>
  <transmission name="motor_002">
    <type>transmission_interface/SimpleTransmission</type>
    <!--関節の指定-->
    <joint name="joint_002">
      <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
    </joint>
    <!--アクチュエータの定義（ギア比1の減速機）-->
    <actuator name="trans_002">
      <hardwareInterface>PositionJointInterface</hardwareInterface>
      <mechanicalReduction>1</mechanicalReduction>
    </actuator>
  </transmission>
  <gazebo>
    <!--関節状態配信プラグインを指定-->
    <plugin filename="libgazebo_ros_joint_state_publisher.so" name="joint_state_publisher">
      <!--対象とする関節名を指定-->
      <jointName>
      ['joint_001', 'joint_002']
      </jointName>
    </plugin>
  </gazebo>
</robot>
```
</details>

##### 説明：3Dモデルの適用
```xml:見た目
    <!-- 見た目 -->
    <visual>
      <geometry>
        <mesh filename="package://fall_sim_001/mesh/side_link.stl"/>
      </geometry>
      <material name="red">
        <color rgba="0.7 0.0 0.0 1.0"/>
      </material>
      <origin rpy="0 0 0" xyz="0 0 0"/>
    </visual>
```
originは原点設定のときに向きなども望みのように調整しておれば，デフォルト（``<origin rpy="0 0 0" xyz="0 0 0"/>``）で問題ないはず．

```xml:干渉ジオメトリ
    <!--物理的特性-->
    <!--干渉-->
    <collision>
      <geometry>
        <mesh filename="package://fall_sim_001/mesh/side_link.stl"/>
      </geometry>
    </collision>
```
##### 説明：3Dモデルのアセンブリ
```xml:fixed_to_base_link
  <joint name="base_joint" type="fixed">
    <parent link="base_link"/>
    <child link="center_link"/>
    <origin rpy="0 0 0" xyz="0.0 0 0"/>
  </joint>
```
```xml:parante_to_child
  <joint name="joint_001" type="revolute">
    <parent link="center_link"/>
    <child link="side_link_001"/>
    <axis xyz="0 1 0"/>
    <origin rpy="0 3.14159265359 0" xyz="-0.056 0 0"/>
    <limit effort="0" lower="-1.57079632679" upper="1.57079632679" velocity="0"/>
  </joint>
  <joint name="joint_002" type="revolute">
    <parent link="center_link"/>
    <child link="side_link_002"/>
    <axis xyz="0 1 0"/>
    <origin rpy="0 0 0" xyz="0.056 0 0"/>
    <limit effort="0" lower="-1.57079632679" upper="1.57079632679" velocity="0"/>
  </joint>
```
** originの部分にパーツ（原点の）間の関係性を設定する．**
（ちなみに，joint_001において，originの回転部分rpyが0でないのは，side_link_001とside_link_002とで用いている3Dモデルを同じにしているにもかかわらず，取り付ける向きが逆であるがゆえに180度回転させている．）
また，limitタグはその回転ジョイントの回転限界を決めている．0基準の-90度から90度（範囲：180度）

### Rvizで確認
##### 原点の確認（TF）
![画像5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951300/7aaac496-083b-2826-86b7-c8316abf0bce.png)

##### ジョイント角度を変更
![画像6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951300/8a087a58-d698-e7d7-7f99-1f80c533b1b5.png)

これは，```joint_state_publisher_gui```を用いて，任意の角度にしている．

## 感想
実際にモデルを作るにあたり，自在に組み合わせるのに必要なことをまとめた．あらかじめ必要なことさえわかっていれば，3Dモデルを設計する時点でもいろいろと工夫できる．また，ここまで自在にできると設計さえできてしまえば，作れるという自信にもつながる．投稿するかは別にして，色々とロボットモデルを作って制御してみるのも面白そうである．シミュレーションはいくらやっても費用がかからないから，存分にやってみたい．モチベーションも上がるし，非常に楽しそうである．これからの学習がさらに充実できそうである．