🦈

ROS2: urdfの作り方とRviz2での表示方法

2022/10/04に公開

海洋ロボコンをやってた人です。
※気になる方は「海洋ロボコン」で調べていただければと思います。

今年で大学を卒業するということもあり、記事として知見を残しておくことにしました。
この記事が初投稿となりますが、どうぞよろしくお願いします。


※2023/02/26追記: 本記事の「ROS2」表記、正しくは「ROS 2」です。

1: ROS2対応 URDFのロボットの作り方

ここでは、ROS2に対応したオリジナルURDFモデルの作り方から、実際にRviz2で表示させるまでを記事にしていこうと思います。

使用するモデルは、アイコンでも表示されているマンタ型ロボットで紹介していきます。
なお、ロボットのハード設計からソフト設計まで全て私が担当しており、所属研究室の教授からも一般公開の許可を得ています。

1.1: はじめに

まずは私が使用した動作環境やソフトを下記に示しておきます。

  • Fusion360 2022/2023
  • Inventor 2022/2023
  • Blender
  • Windows10
  • Ubuntu 20.04

Inventor および Blenderは無くても問題ありません。
また、ここではCADの操作方法, Linuxコマンドの説明を割愛させていただくことがあります。

1.2: 本記事のプログラム

下記のGithubにて公開しているので、こちらを参考にしてください。
スター頂けると、大変嬉しいです・ω・

https://github.com/tasada038/manta_v2

1.3: 3DモデルからURDFを出力する

Fusion2urdf

3DモデルからURDFを出力する方法として、広く使われているfusion2urdfというプラグインを使用します。

こちらの使い方は株式会社アールティ様のブログ:二足歩行ロボット研修(kora編)[21] Fusion360のモデルからURDFを生成するが非常に参考になります。
執筆してくださった方、本当に勉強になりました。ありがとうございます。

上記より、プラグインのインストールができたら、「joint」や「slider」を用いてアセンブリをしていきましょう。座標系はZaxis UPとなるように配置します。

コンポーネント名は

  • base_link
  • link1

など分かりやすい英語名で付けると良いと思います。

この"コンポーネント名"ですが、アセンブリパーツだと上手くurdf_descriptionが出力されない可能性があります。

なので、コンポーネント単位のパーツとなるようにFusion360側でデータを変換しておきます。

CADデータが変わりますが、修正 > 結合と進み新規コンポーネントにチェックを入れてパーツを結合します。

新規コンポーネント作成後、コンポーネントを選択した後、右クリックで(コンポーネントの)コピーを名前をつけて保存します。

この新規作成したコンポーネント同士を使用して、アセンブリしていけばOKです。


また、これは後から思ったことですが、Fusion360にインポートする際に

  • link_Rtop_roll1_1

と最後に予期していない"_数字"が付いてしまうので、これが美しくないと感じる方はFusion360のコンポーネント名で名前を変えておくと良いと思います。

ジョイントも同様に設定をしていきます。
-リジッド
-回転
-スライダー
など、任意のアセンブリを行い、"ジョイントの制限を編集"より可動域を設定することも忘れないでください。

上記の設定ができたら

  • ユーティリティ>アドイン>マイスクリプト>URDF_Exporter

より、ROS1用のパッケージを出力します。

ROS2対応のfusion2urdf(Fusion360で作成したCADモデルをURDF化し、Unityに召喚し操作する)もあります。

私は出力されるパッケージがROS1の方が楽にROS2対応用に書き換えれるので、ROS1用のスクリプトを使用しています。
プログラムを読み慣れている方で作成してもらえば良いと思います。


また、パッケージ名は

  • アセンブリ名_description
    として出力されるので、こちらも使いやすい名前にしておきましょう。

Fusion360のみだと、これでURDFの準備は終了です。

Inventor Professionalの場合

AutoDesk Inventor Professional を使用している場合は少し工程が増えます。
Fusion360でURDF用のアセンブリを作製する場合、すべてコンポーネント形式で行います。

そのため、Inventor側で".iam"ファイルを".ipt"ファイルに変換しておく必要があります。

手順としては

  1. .iamを開く
  2. headerのアセンブリ > 簡略化 > 簡略化パーツを作成
  3. テンプレート(T) Sheet Metal.ipt → Standard.iptへ変更

として.iptファイルを出力します。

これを、自由度を持つパーツごとに.iptファイルとして準備しておきましょう。

1.4: COLLADA(dae)に変換する場合

.stlファイルを.daeのCOLLADAファイルに変換することで、3Dモデルに様々なデザインを追加することができます。

COLLADAファイルの作製にあたり、Ryodo Tanaka様のこちらの記事が大変勉強になりました。ありがとうございます。
Gazebo + ROS で自分だけのロボットをつくる 3.COLLADAファイルをつくる

こちらでも、一通り自分が行った工程を備忘録として記載しておきます。

モデルのインポートとUV展開

  • File > Import >stl

より、.daeに変換した.stlをパーツ単位でインポートします。

点キーの"1", "3", "7"などでモデルviewの向きを変更することもできます。
ここではZ軸上面から見えるように点キー7を押しました。


モデルを選択(またはショートカットAで全選択)し

  • オブジェクトモード > 編集モード

へ変更します。


続いて"UV Editing"によりUV用のパネルを開き

  • headerの画像 > 新規画像:New > Generated type: "blank" → "uv grid"

として、UV展開用の下地を準備します。

モデル側のパネルにて

  • A (全選択) > U (UV展開) > ビューから投影

をクリックしていき、Z軸から見た投影図をUVパネル側に反映させます。

ビューから投影すると、投影図が小さい場合があり、色を塗るときに扱いにくいことがあります。
そのため、左側のメニューから"Transform"で位置・サイズを変更しておきましょう。


最後に

  • UV > UV配置をエクスポート

でUV展開の.pngファイルを出力します。

オプション: パーツ単位でUV展開する場合

パーツ単位でUV展開して色分けをしたい場合は、Seamで分割領域を分けてUV展開する必要があります。

3Dのメモ帳 様のYoutubeを参考に、こちらも試してみます。

モデルview側で"辺選択"に切り替えて、分割領域をShiftキーを押しながら、地道に分けていきます。
頂点、辺、面選択の切り替えは、点キーでない数字の1, 2, 3がショートカットです。

上記のように囲えたら

  • U > Mark seam

でシームを作成します。

続いて、"面選択"に切り替え、Seamで囲った箇所にカーソルを合わせ"Lキー"を押します。
すると、シームで囲った領域を選択することが出来ます。
UV Editing側でも"面選択"にしておきましょう。

この状態で

  • U > 展開

を押すと、シームで囲った領域が別途UV展開されます。

COLLADA用に色をつける

出力された.pngをペイントソフトなどに読み込ませ、色を付けていきます。
私はPhotoshopが使いなれているため、こちらで紹介させていただきます。

.pngをPsに読み込ませたら

  • Ctrl + J でUV展開画像をバックアップとして複製する
  • Ctrl + Shift + Nで新規レイヤを作成
  • G > 白色選択 > 新規レイヤを塗りつぶす
  • UV展開のレイヤ-と白で塗りつぶしたレイヤをCtrl + Eで結合
  • 選択範囲 > 色域選択 > 白を選択 または クイック選択ツール(W)で白を選択
  • Ctrl + Shift + Iで選択範囲を反転

ここまでの作業で、UV展開図の輪郭部を選択ツールで囲うことができます。
選択ツールで囲うことで、ブラシで色を塗る際に、色がはみ出ることなく簡単に色塗りできます。

このように色を塗り終えたら、

  • 選択範囲 > 色域選択 > 白を選択 または クイック選択ツール(W)で白を選択

で白を選択し、Deleteキーで白をなくせば.pngをつくることができます。

最後に

  • Ctrl + Shift + Alt + S

で名前を付けて書き出しで、色付きUV展開図を出力します。

.daeをエクスポートする

.pngに色をつけれたら、UV Ediging側にドラッグ&ドロップで.pngを読み込ませます。
ファイル名が読み込んだものと一致するように、変更もしてください。

次に、モデルview側で

  • マテリアル > 新規 > サーフェス > ノードを使用をクリック
  • ベースカラー > 右の●をクリック > 画像テクスチャ > 読み込んだ画像を選択

し、サーフェイスにUV展開図を紐づけます。

ここで、モデルにUV展開図の色が反映されてなくても問題ありません。
Shadingでノードや色が反映されていればOKです。

また、オプションのmark seamで分割しない場合は、どうやら色が上下に反映されるようで、綺麗な見栄えのモデルを作りたい場合は、しっかりとUV展開をした方が良いかと思います。

最後に

  • Export > COLLADA > 選択中のUVマップのみコピーにチェック

して.daeファイルを出力して完成です。

出力された".dae"とUV展開に使用した".png"をfusion2urdfで出力された"xxx_description/meshes/"にコピーして準備完了です。

また、".stl"を".dae"にそのままエクスポートするだけにBlenderを使うのも良いと思います。

1.5: URDFをROS2用に変更する

さて、ここからやっとプログラムに入ることができます。
上記で作成したxxx_descriptionや.daeがmeshesに入っていることを確認して、Ubuntu側にフォルダを移動しましょう。パッケージはこのように構成になっていると思います。

任意の場所にcatkin_wsを作成して、ROS1でdescriptionが動くことを確認してもらっても構いません。(ROS1での動作確認は割愛)

ROS2用に各ファイルを書き換える

以下よりファイルを書き換えていきますが、知識不足により至らぬ点があるかもしれませんが、ご了承ください。


  • CMakeLists.txt

まずは既存のCMakeLists.txt全文を下記のように書き換えます。
project(xxx_description)のみパッケージ名とするようにしてください。

CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(manta_v2_description)

# Default to C++14
if(NOT CMAKE_CXX_STANDARD)
  set(CMAKE_CXX_STANDARD 14)
endif()

find_package(ament_cmake REQUIRED)

install(DIRECTORY
  rviz
  meshes
  urdf
  DESTINATION share/${PROJECT_NAME}/
)

ament_package()


  • package.xml

こちらは、ROS1でのbuild toolであるcatkinをROS2用のament_cmakeに変更してきます。
rospyなどのdependも削除or変更します。

package.xml
+   <buildtool_depend>ament_cmake</buildtool_depend>
+   <exec_depend>rviz2</exec_depend>
+   <exec_depend>xacro</exec_depend>
+   <export>
+     <build_type>ament_cmake</build_type>
+   </export>
-   <buildtool_depend>catkin</buildtool_depend>
-   <build_depend>rospy</build_depend>
-   <build_export_depend>rospy</build_export_depend>
-   <exec_depend>rospy</exec_depend>
-   <export>
-   </export>


  • urdf.rviz

新規フォルダでrvizフォルダを作成し、launchフォルダ内のurdf.rvizを、rvizフォルダ内へ移動します。
その後、以下を書き換えていきます。

urdf.rviz
Panels:
+ Class: rviz_common/Displays
- Class: rviz/Displays

 Visualization Manager:
+ Class: rviz_default_plugins/Grid
- Class rviz/Grid

-  - Class: rviz_common/Time
-    Experimental: false
-    Name: Time
-    SyncMode: 0
-    SyncSource: ""
-Preferences:
-  PromptSaveOnExit: true
-Toolbars:
-  toolButtonStyle: 2

Window Geometry:
-  Time:
-    collapsed: false

RobotDescriptionトピックの設定
+      Collision Enabled: false
+      Description File: ""
+      Description Source: Topic
+      Description Topic:
+        Depth: 5
+        Durability Policy: Volatile
+        History Policy: Keep Last
+        Reliability Policy: Reliable
+        Value: /robot_description

ざっとこれらを編集しましたが、詳しくはGitHubをご覧ください。

また、Robot Description下のlink名などにservobottom_linkなどがある場合は、これらはすべて不要なので、削除してOKです。


  • urdfフォルダ

fusion2urdfでパッケージを出力すると、xxx.urdfではなくxxx.xacroというXML形式でファイルが作られます。

これらは特に変更しなくても問題ありませんが、見やすさを考慮し少し手を加えます。

  1. packages_name_description.xacroをurdfフォルダ内で新規作成

  2. packages_name.xacroのlinkタグ, jointタグの情報を上記のファイルに切り取り&ペースト

  3. その際に、xml, robotタグで囲う

  4. xacro:macroによりparamsを使っても良い(任意)

また、下記のxacroファイルは<link>タグや<joint>タグの一部を抜粋して記載しており、全文ではありません。

manta_v2_description.xacro
<?xml version="1.0" ?>
<robot name="manta_v2" xmlns:xacro="http://www.ros.org/wiki/xacro" >
  <xacro:macro name="manta_v2_description" params="main_color sub_color">
    <link name="base_link">
      <inertial>
      </inertial>
      <visual>
        <origin xyz="0 0 0" rpy="0 0 0"/>
        <geometry>
          <mesh filename="package://manta_v2_description/meshes/base_link.stl" scale="0.001 0.001 0.001"/>
        </geometry>
        <material name="${main_color}"/>
      </visual>
      <collision>
      </collision>
    </link>
    <joint name="con_link_Lbtm_end" type="fixed">
      <origin xyz="-0.033288 0.154418 8.8e-05" rpy="0 0 0"/>
      <parent link="link_Lbtm_roll2_1"/>
      <child link="link_Lbtm_end_1"/>
    </joint>
  </xacro:macro>
</robot>

こちらは、xacroの全文です。

manta_v2.xacro
<?xml version="1.0" ?>
<robot name="manta_v2" xmlns:xacro="http://www.ros.org/wiki/xacro">

<xacro:include filename="$(find manta_v2_description)/urdf/materials.xacro" />
<xacro:include filename="$(find manta_v2_description)/urdf/manta_v2.trans" />
<xacro:include filename="$(find manta_v2_description)/urdf/manta_v2.gazebo" />
<xacro:include filename="$(find manta_v2_description)/urdf/manta_v2_description.xacro" />
<xacro:manta_v2_description main_color="grey" sub_color="white" />

</robot>

また、meshesの色はmaterials.xacro内に記述しておく

materials.xacro
<?xml version="1.0" ?>
<robot name="manta_v2" xmlns:xacro="http://www.ros.org/wiki/xacro" >
 <material name="grey">
    <color rgba="0.25 0.25 0.25 1.0"/>
  </material>
  <material name="white">
    <color rgba="1.0 1.0 1.0 1.0"/>
  </material>
</robot>

これで、description packagesは完成なので、続いてlaunch するためのbringup packagesを作成していきます。

ROS2用にbringupパッケージをつくる

packages_name_descriptionのあるワークスペースで

ros2 pkg create --build-type ament_cmake packages_name_bringup

として新しいパッケージを作成します。

作成後、packages_name_description下のlaunchファイルをpackages_name_bringup下に切り取り&コピーしておきましょう。

また、bringup内のinstall, srcフォルダを不要なので削除し、launchフォルダを加えたため、CMakeList.txtを変更します。

CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(manta_v2_bringup)

# Default to C++14
if(NOT CMAKE_CXX_STANDARD)
  set(CMAKE_CXX_STANDARD 14)
endif()

find_package(ament_cmake REQUIRED)

install(
  DIRECTORY launch
  DESTINATION share/${PROJECT_NAME}
)

ament_package()

続いて、launchフォルダ内にdisplay.launch.pyを作成し、以下のように記述してください。
また、下記の名前も変更してください。

  • packages_name = "xxx_description"
  • xacro_file_name = "xxx.xacro"
display.launch.py
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.substitutions import Command, FindExecutable, LaunchConfiguration, PathJoinSubstitution

from launch_ros.actions import Node
from launch_ros.substitutions import FindPackageShare


def generate_launch_description():

    packages_name = "manta_v2_description"
    xacro_file_name = "manta_v2.xacro"
    rviz_file_name = "urdf.rviz"

    # Get URDF via xacro
    robot_description_content = Command(
        [
            PathJoinSubstitution([FindExecutable(name="xacro")]),
            " ",
            PathJoinSubstitution(
                [FindPackageShare(packages_name), "urdf", xacro_file_name]
            ),
        ]
    )
    robot_description = {"robot_description": robot_description_content}

    rviz_config_file = PathJoinSubstitution(
        [FindPackageShare(packages_name), "rviz", rviz_file_name]
    )

    robot_state_pub_node = Node(
        package="robot_state_publisher",
        executable="robot_state_publisher",
        output="both",
        parameters=[robot_description],
    )
    joint_state_pub_gui_node = Node(
        package="joint_state_publisher_gui",
        executable="joint_state_publisher_gui",
        output="screen",
    )
    rviz_node = Node(
        package="rviz2",
        executable="rviz2",
        name="rviz2",
        output="log",
        arguments=["-d", rviz_config_file],
    )

    nodes = [
        rviz_node,
        robot_state_pub_node,
        joint_state_pub_gui_node,
    ]

    return LaunchDescription(nodes)

ここまで終われば、

cd ~/xxxxx_ws
colcon build

でビルドして、ビルドが通れば準備完了ですね。

Rviz2で表示させる

ターミナルで以下を打ち込み、プログラムを実行しましょう。

なお、”joint_state_publisher_gui”をインストールしていない場合は

sudo apt install ros-$ROS_DISTRO-joint-state-publisher*

でパッケージをインストールしておきます。

cd ~/xxxxx_ws
. install/setup.bash
ros2 launch manta_v2_bringup display.launch.py

実行結果です。

うまく.daeやモデルが反映されていることが確認できますね。

疑問点、改善点等あればお気軽にご連絡ください。
また、この記事が良かったと感じたら、"いいね"ボタンよろしくお願いします。

以上。


  • 2023/03/11追記

xacroパッケージを使用することで、aaa.xacroからbbb.urdfへ変換することが可能です

インストール

sudo apt install ros-$ROS_DISTRO-xacro

変換

ros2 run xacro xacro aaa.xacro > bbb.urdf

Discussion