ロボット開発記録

ロボット開発の進捗や記録をするブログ

URDFから情報を抽出してROS 2パラメータにする [ヒューマノイド動歩行]

前回の記事↓ odome.hatenablog.com

開発リポジトリgithub.com

概要

 ヒューマノイドロボットのモデルが記述されたURDFファイルを読み込み、制御に有用な情報をROS 2パラメータとして利用可能なYAMLファイルで出力するPythonスクリプトを作成しました。本記事では、このスクリプトの紹介を行います。

(後述しているように動作確認はしていますが、どのURDFモデルでも正常に動作する保証はいたしかねます。生成されたYAMLファイルが正常が正しいかを確認することを推奨します。)

3行で説明

  • URDFファイルを読んでROS 2パラメータのYAMLファイルを生成するスクリプトmodel_parameter_generator.pyを作った(source_code)。

  • URDFモデルはヒューマノイドロボットを対象とし、動作試験はROBOTIS OP2のXacroをURDFに変換したもので行った(source_code & readme)。

  • 生成されるYAMLファイルは、全関節の情報、四肢(正確にはツリー構造の枝ごと)ごとのリンク長や名前をまとめたもの、全関節名をまとめたもの、計3つ生成し、主に/joint_statesトピックや運動学計算での活用を想定している。

動機

 スクリプトを作成するに至った動機を以下に示します。

  • 運動学計算や/joint_statesトピックの作成には、ロボットの各リンク長や関節名を、ユーザ側でURDFファイルを直接読んでコードに反映する必要がある。

  • 制御対象とするロボットモデルを変更する際に、再度URDFを読んでコードに反映するという作業は苦痛。加えて、書き換えるべきコードを理解しておく必要がある。

  • ROS 2パラメータでURDF内の必要な情報を扱えれば、コード理解と書き換え作業を削減できるのでは?

つまりは、制御対象を変更する作業を、より簡単で容易にできるようにしたい、これが動機であり、目的となります。

使用方法

 ここでは、本スクリプトの使用方法について示します。ソースコードは以下となっています。

github.com

使用方法

  1. スクリプトを実行する前に,対象とするURDF ファイルが robot_description/models/<ロボットの名前>/ディレクトリ内に置かれていること,プログラム内で定義されているURDFファイル名とロボットの名前が正しいかを確認する.

  2. スクリプトであるrobot_tools/robot_tools/model_parameter_generator.pyを実行する.(以下、例)

cd robot_tools/robot_tools/  # 移動
./model_parameter_generator.py  # 実行
  1. 四肢などの URDF 内に含まれるツリーが表示されるので,指示通りに各ツリーの名前を入力する.(以下、例)
[INFO] Robot name is robotis_op2
[WARNING] Already robot_description/config/robotis_op2 dir.
[INFO] List of tree in URDF file. (with fixed joints)
   tree 0 : ['base_joint']
   tree 1 : ['head_pan', 'head_tilt', 'head_cam']
   tree 2 : ['l_sho_pitch', 'l_sho_roll', 'l_el']
   tree 3 : ['r_sho_pitch', 'r_sho_roll', 'r_el']
   tree 4 : ['l_hip_yaw', 'l_hip_roll', 'l_hip_pitch', 'l_knee', 'l_ank_pitch', 'l_ank_roll']
   tree 5 : ['r_hip_yaw', 'r_hip_roll', 'r_hip_pitch', 'r_knee', 'r_ank_pitch', 'r_ank_roll']

[INFO] Please input free joint_tree_name.
[INFO] If nothing is inputted, joint_tree_name is 'names_group_<number>'.
[INFO] tree 0 name? >  # ここに、tree 0の名前を入力
  1. 右脚と左脚のツリー名を指定する.(以下、例)
name's number | joint_group_name | joint_group_value
--------------|------------------|------------------
      0       |  names_group_0   | ['base_joint']
      1       |  names_group_1   | ['head_pan', 'head_tilt', 'head_cam']
      2       |  names_group_2   | ['l_sho_pitch', 'l_sho_roll', 'l_el']
      3       |  names_group_3   | ['r_sho_pitch', 'r_sho_roll', 'r_el']
      4       |  names_group_4   | ['l_hip_yaw', 'l_hip_roll', 'l_hip_pitch', 'l_knee', 'l_ank_pitch', 'l_ank_roll']
      5       |  names_group_5   | ['r_hip_yaw', 'r_hip_roll', 'r_hip_pitch', 'r_knee', 'r_ank_pitch', 'r_ank_roll']

[INFO] What's left_leg's name? (please input name's number) >  # ここに、左脚のname's numberを入力
  1. YAML ファイルが robot description/config/<ロボットの名前>/ディレクトリ内に生成される.

出力結果

 ここでは、本スクリプトが出力するYAMLファイルについて示します。

  • param_<ロボットの名前>_joints.yaml
    • 全関節の回転軸方向やリミットなどの情報を持つ。
    • position_sensor_nameは、webotsで関節角度を取得する際に用いるセンサ名。以下同様。(以下、例)
/**:
  ros__parameters:
    robotis_op2_joints:
      base_joint:
        origin:
          xyz:
          - 0.0, 0.0, 0.0
          rpy:
          - 0.0, 0.0, 0.0
      head_pan:
        position_sensor_name: head_pan_sensor
        origin:
          xyz: 0 0 0.0205
          rpy: 0 0 0
        axis: 0 0 1
        limit:
          effort: 2.8
          lower: -2.6179939
          upper: 2.6179939
          velocity: 5.6548668
      head_tilt:
        position_sensor_name: head_tilt_sensor
        origin:
          xyz: 0 0 0.03
          rpy: 0 0.5759586531581288 0
        axis: 0 -1 0
        limit:
          effort: 2.8
          lower: -2.6179939
          upper: 2.6179939
          velocity: 5.6548668
...
  • param_<ロボットの名前>_limb.yaml
    • 四肢などのそれぞれの名前リストやリンク長のリストを持つ。
    • 特に、運動学計算や/joint_statesトピックで有用であると思われる。
    • 駆動しない関節(fixed)を含むリストと、含まないリスト両方を記録している。(以下、例)
/**:
  ros__parameters:
    robotis_op2_limb:
      limb_names:
        left_leg: l_leg
        right_leg: r_leg
      limb_without_fixed_joints:
        base:
          joint_names: null
          position_sensor_names: 'null'
          joint_numbers: null
          joint_unit_vector: null
          link_length: null
          joint_posture: null
        head:
          joint_names:
          - head_pan
          - head_tilt
          position_sensor_names:
          - head_pan_sensor
          - head_tilt_sensor
          joint_numbers:
          - 0
          - 1
          joint_unit_vector:
          - 0 0 1
          - 0 -1 0
          link_length:
          - 0 0 0.0205
          - 0 0 0.03
          joint_posture:
          - 0 0 0
          - 0 0.5759586531581288 0
        l_arm:
          joint_names:
          - l_sho_pitch
          - l_sho_roll
          - l_el
          position_sensor_names:
          - l_sho_pitch_sensor
          - l_sho_roll_sensor
          - l_el_sensor
          joint_numbers:
          - 2
          - 3
          - 4
          joint_unit_vector:
          - 0 1 0
          - -1 0 0
          - 0 1 0
          link_length:
          - 0 0.0575 0
          - 0 0.0245 -0.016
          - 0.016 0 -0.06
          joint_posture:
          - 0 0 0
          - 0.7853981633974483 0 0
          - 0 -1.5707963267948966 0
  • param_<ロボットの名前>_name_lists.yaml
    • 全関節名と全position_sensor名を持つ。
    • 特に、/joint_statesトピックで有用であると思われる。
    • 駆動しない関節(fixed)を含むリストと、含まないリスト両方を記録している。(以下、例)
/**:
  ros__parameters:
    robotis_op2_name_lists:
      all_names_without_fixed_joints:
        all_joint_names:
        - head_pan
        - head_tilt
        - l_sho_pitch
        - l_sho_roll
        - l_el
        - r_sho_pitch
        - r_sho_roll
        - r_el
        - l_hip_yaw
        - l_hip_roll
        - l_hip_pitch
        - l_knee
        - l_ank_pitch
        - l_ank_roll
        - r_hip_yaw
        - r_hip_roll
        - r_hip_pitch
        - r_knee
        - r_ank_pitch
        - r_ank_roll
        all_position_sensor_names:
        - head_pan_sensor
        - head_tilt_sensor
        - l_sho_pitch_sensor
        - l_sho_roll_sensor
        - l_el_sensor
        - r_sho_pitch_sensor
        - r_sho_roll_sensor
        - r_el_sensor
        - l_hip_yaw_sensor
        - l_hip_roll_sensor
        - l_hip_pitch_sensor
        - l_knee_sensor
        - l_ank_pitch_sensor
        - l_ank_roll_sensor
        - r_hip_yaw_sensor
        - r_hip_roll_sensor
        - r_hip_pitch_sensor
        - r_knee_sensor
        - r_ank_pitch_sensor
        - r_ank_roll_sensor

そしてこれらROS 2パラメータファイルは、前々回の記事で紹介したParameter Serverに読み込まれ、各ノードからROS 2パラメータとして扱えるようになっています。

前々回の記事↓ odome.hatenablog.com

以上の実装によって、URDF内の情報をROS 2パラメータで扱えるようにしています。

最後に

 今回は、URDFから情報を抽出してROS 2パラメータとして利用できるようにする、model_parameter_generator.pyの紹介を行いました。はじめに述べたように、どのURDFモデルでも正しいYAMLファイルを生成できることを保証することはできていませんが、スクリプトの利用によってロボットモデルを変更しやすくなったと思います。
 今後の展望として、エラー処理の追加や、他URDFファイルでの実例を増やしていければ良いと考えています。

開発リポジトリgithub.com