差動車輪付きロボットを例として、URDF ロボット モデリングと xacro 最適化を学びます
1 リソース
この記事は ROS Efficient Advanced の第 2 章であり、URDF 言語 (xml 形式) を使用して差動車輪付きロボット モデルを作成し、拡張バージョンの URDF xacro を使用してロボット モデル ファイルの二次最適化を実行します。
ディファレンシャルホイールロボット:二輪ディファレンシャルシャーシはシャーシの左右に配置された2つの動力輪で構成され、2つの車輪が独立して速度を制御し、異なる速度を与えることでシャーシのステアリング制御を実現します。一般に、補助サポート用に 1 つまたは 2 つのユニバーサル ホイールが装備されます。
このモデリングではアルゴリズムは導入せず、ロボットモデルの外観のみを作成するため、視覚的な表示には rivz のみを使用します。
この記事の参考文献:
(0)二輪差動ロボット運動学モデル
(1) 『ROS ロボット開発実践』第 5 章と第 6 章、Hu Chunxu (
2) ROS 探索の概要: URDF の解釈
(3) ROS 探索の概要:どのようにゼロから始めるロボットモデル(ロボットアーム)の作成
(4) ROS Efficient Advanced 第 1 章 – ROS Advanced Components の rviz
2 テキスト
2.1 ロボットの定義と構成
(1) ロボットの定義: ロボットは自動化された機械であり、認識、計画、行動、調整などの人間や生き物と同様の知的能力を備え、柔軟性を備えた高度な自動機械です。
現在、自動運転車もロボットの一種とみなされています。
(2) ロボットの構成: ロボットは通常、アクチュエータ、駆動系、センシング系、制御系の 4 つの部分に分かれます。
自動運転車を例にとると、アクチュエーターはアクセル、ステアリング、ブレーキ、駆動システムはモーター、センシングシステムは各種センサー(ライダー、レーダー、カメラ、uss、imu、GNSS)、制御システムはインテリジェントな運転アルゴリズム システム: 知覚、位置決め、計画および制御。
(3) ロボットの主要 4 つの部分の制御ループは大まかに図に示すとおりです。
2.2 URDF モデリング ルーチン
(1) URDF: Unified Robot description Format、統一ロボット記述ファイル形式。urdf ファイルは XML 形式を使用します。
(2) urdf を使用してロボットを記述すると、ルーチンは次のようになります。各ロボットは複数のリンク (コネクティング ロッド) とジョイント (関節) で構成されます。ここでのリンクとジョイントは非常に幅広く、形状は必ずしも棒や軸ではありません。たとえば、テーブル、天板、脚はすべてリンクであり、関節は固定関節です。
<?xml version="1.0" ?>
<robot name="name of robot">
<link> ... </link>
<joint> ... </joint>
...
</robot>
(3) リンク: ロボットの剛体部分の外観と物理的特性を説明します。外観には、サイズ、色、形状が含まれます。物理的プロパティには、慣性マトリックス (慣性マトリックス) と衝突パラメーター (衝突プロパティ) が含まれます。ロボット モデリングでは、各リンクは座標系です。
以下は、一般にベースと呼ばれる差動ホイールロボットのシャーシのモデリングです。
<link name="base_link">
// visual 标签就是外观
<visual>
// base_link本身是个坐标系,这也是差速轮式机器人各组成部分的根坐标系,一般会把他的坐标原点设置在rviz的中心处
// origin表示底盘在其base_link坐标系下的原始位置和旋转状态
// xyz表示底盘质心在base_link坐标系的偏移位置,rpy(roll,pitch,yaw)是底盘绕base_link的x,y,z三个轴的旋转值
<origin xyz="0 0 0" rpy="0 0 0"/>
// geometry是物体几何外形
<geometry>
// 这里的底盘,用圆柱体表示,length值为高度,radius是半径值
<cylinder length="0.16" radius="0.2"/>
</geometry>
// material是材料,这里指定底盘颜色为红色,rgba是三色+透明度表示法,三色的范围是0~1,而不是0-255
<material name="red">
<color rgba="1 0 0 1"/>
</material>
</visual>
</link>
補足:ここでは外観モデリングのみなので物理属性の設定は当面は行いませんが、次章のガゼボ上でシミュレーションする際にサンプルのリンクに物理属性を追加していきます。
(4) ジョイント: 運動学属性とダイナミクス属性を含む 2 つのリンク間の関係を記述します。ここでは運動学属性のみに焦点を当てます。通常、2 つのリンク間の関係は、次の 6 つのタイプに分類されます。
continuous:旋转关节,可以围绕单轴360度无限旋转,比如轮子的轴
revolute:旋转关节,但是有旋转角度的范围限制,比如钟摆
prismatic:滑动关节,也叫活塞关节,沿某一轴线移动的关节,有位置限制,强调一维,比如打气筒
planar:平面关节,允许在平面正交方向上平移或旋转,强调平面,比如抽屉内外滑动
floating:浮动关节,允许进行平移和旋转运动,比如人体的肩关节
fixed:固定关节,比如桌子腿和桌面
以下は、差動ホイールロボットの駆動輪とシャーシ間の接合例です。
// joint标签就是关节,type表示链接关系
<joint name="left_wheel_joint" type="continuous">
// origin表示轮子在base_link坐标系下的偏移和旋转
<origin xyz="0 0.19 -0.05" rpy="0 0 0" />
// 根link是底盘,子link是轮子
<parent link="base_link" />
<child link="left_wheel_link" />
// axis描述的轮子相对于其自身坐标系的 y 轴旋转,=
<axis xyz="0 1 0" />
</joint>
// 这是轮子link
<link name="left_wheel_link">
<visual>
// 轮子相当于其x轴,旋转90度,也就是立起来
<origin xyz="0 0 0" rpy="1.5707 0 0"/>
<geometry>
<cylinder length="0.06" radius="0.06"/>
</geometry>
<material name="white">
<color rgba="1 1 1 0.9"/>
</material>
</visual>
</link>
2.3 URDF を使用して差動車輪付きロボット モデルを作成する
(1) mbot_description パッケージと関連ファイルの作成
cd ~/catkin_ws/src
catkin_create_pkg mbot_description urdf xacro
cd mbot_description
mkdir -p config doc launch meshes urdf/sensor
touch launch/display_mbot_urdf.launch launch/display_mbot_xacro.launch
touch urdf/mbot_base.urdf urdf/mbot_base.xacro
touch urdf/sensor/camera.xacro urdf/sensor/kinect.xacro urdf/sensor/laser.xacro
(2) mbot_base.urdf: これは、シャーシ、2 つのパワー ホイール、2 つのユニバーサル ホイール、カメラ、kinect (深度カメラ)、および LIDAR を含む、mbot モデリング ファイル全体です。具体的な文法については前のセクションの紹介を参照してください。ここでは繰り返しません。
<?xml version="1.0" ?>
<robot name="mbot">
<link name="base_link">
<visual>
<origin xyz="0 0 0" rpy="0 0 0"/>
<geometry>
<cylinder length="0.16" radius="0.2"/>
</geometry>
<material name="red">
<color rgba="1 0 0 1"/>
</material>
</visual>
</link>
<joint name="left_wheel_joint" type="continuous">
<origin xyz="0 0.19 -0.05" rpy="0 0 0" />
<parent link="base_link" />
<child link="left_wheel_link" />
<axis xyz="0 1 0" />
</joint>
<link name="left_wheel_link">
<visual>
<origin xyz="0 0 0" rpy="1.5707 0 0"/>
<geometry>
<cylinder length="0.06" radius="0.06"/>
</geometry>
<material name="white">
<color rgba="1 1 1 0.9"/>
</material>
</visual>
</link>
<joint name="right_wheel_joint" type="continuous">
<origin xyz="0 -0.19 -0.05" rpy="0 0 0" />
<parent link="base_link" />
<child link="right_wheel_link" />
<axis xyz="0 1 0" />
</joint>
<link name="right_wheel_link">
<visual>
<origin xyz="0 0 0" rpy="1.5707 0 0"/>
<geometry>
<cylinder length="0.025" radius="0.06" />
</geometry>
<material name="white">
<color rgba="1 1 1 0.9"/>
</material>
</visual>
</link>
<joint name="front_caster_joint" type="continuous">
<origin xyz="0.18 0 -0.095" rpy="0 0 0" />
<parent link="base_link"/>
<child link="front_caster_link" />
<axis xyz="0 1 0" />
</joint>
<link name="front_caster_link">
<visual>
<origin xyz="0 0 0" rpy="0 0 0" />
<geometry>
<sphere radius="0.015" />
</geometry>
<material name="white">
<color rgba="1 1 1 0.9"/>
</material>
</visual>
</link>
<joint name="back_caster_joint" type="continuous">
<origin xyz="-0.18 0 -0.095" rpy="0 0 0" />
<parent link="base_link"/>
<child link="back_caster_link" />
<axis xyz="0 1 0" />
</joint>
<link name="back_caster_link">
<visual>
<origin xyz="0 0 0" rpy="0 0 0" />
<geometry>
<sphere radius="0.015" />
</geometry>
<material name="white">
<color rgba="1 1 1 0.9"/>
</material>
</visual>
</link>
<joint name="camera_joint" type="fixed">
<origin xyz="-0.17 0 0.1" rpy="0 0 0" />
<parent link="base_link"/>
<child link="camera_link" />
</joint>
<link name="camera_link">
<visual>
<origin xyz="0 0 0" rpy="0 0 0" />
<geometry>
<box size="0.03 0.04 0.04" />
</geometry>
<material name="grey">
<color rgba="0.5 0.5 0.5 1"/>
</material>
</visual>
</link>
<joint name="stage_joint" type="fixed">
<origin xyz="0 0 0.14" rpy="0 0 0" />
<parent link="base_link"/>
<child link="stage_link" />
</joint>
<link name="stage_link">
<visual>
<origin xyz="0 0 0" rpy="0 0 0"/>
<geometry>
<cylinder length="0.12" radius="0.1"/>
</geometry>
<material name="red">
<color rgba="1 0 0 1"/>
</material>
</visual>
</link>
<joint name="laser_joint" type="fixed">
<origin xyz="0 0 0.085" rpy="0 0 0" />
<parent link="stage_link"/>
<child link="laser_link" />
</joint>
<link name="laser_link">
<visual>
<origin xyz="0 0 0" rpy="0 0 0" />
<geometry>
<cylinder length="0.05" radius="0.05"/>
</geometry>
<material name="grey">
<color rgba="0.5 0.5 0.5 1"/>
</material>
</visual>
</link>
<joint name="kinect_joint" type="fixed">
<origin xyz="0.15 0 0.11" rpy="0 0 0" />
<parent link="base_link"/>
<child link="kinect_link" />
</joint>
<link name="kinect_link">
<visual>
<origin xyz="0 0 0" rpy="0 0 1.5708" />
<geometry>
// 使用三维软件导出的模型文件
<mesh filename="package://mbot_description/meshes/kinect.dae" />
</geometry>
</visual>
</link>
</robot>
(3)display_mbot_urdf.launch
<launch>
// 设置ros的全局参数robot_description,指定机器人模型文件
<param name="robot_description" textfile="$(find mbot_description)/urdf/mbot_base.urdf" />
<!-- 设置GUI参数,显示关节控制插件 -->
// 用这个可以控制机器人关节,但本文的demo没看到这个,有点遗憾
<param name="use_gui" value="true"/>
<!-- 运行joint_state_publisher节点,发布机器人的关节状态 -->
<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" />
<!-- 运行robot_state_publisher节点,发布tf -->
<node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" />
// robot_state_publisher结合joint_state_publisher可以实时把机器人各关节和各坐标系关系发布出来,让rviz显示。如果不设置,rviz无法完整加载机器人模型。
// rviz显示后会生成配置文件,保存后再打开,就不用频繁设置了。
<!-- 运行rviz可视化界面 -->
<node name="rviz" pkg="rviz" type="rviz" args="-d $(find mbot_description)/config/mbot_urdf.rviz" required="true" />
</launch>
(4) urdf_to_graphiz コマンド ライン ツールを使用して、urdf ファイルの内容を pdf 形式のツリー形式でダンプします。これを使用して、urdf のリンクとジョイントをすばやく読み取ります。次の図は、上記の例のノード ツリー図です。
cd ~/catkin_ws/
urdf_to_graphiz src/mbot_description/urdf/mbot_base.urdf
(5) コンパイルして実行する
cd ~/catkin_ws/
catkin_make --source src/mbot_description
source devel/setup.bash
roslaunch mbot_description display_mbot_urdf.launch
2.4 xacro を使用した差動車輪ロボット モデルの最適化
(1) 元の urdf 構文は比較的単純であるため、ロボット モデル ファイルは長くなり、たとえば 2 つのパワー ホイールと 2 つのユニバーサル ホイールの記述は非常に反復的になります。ROS は、パラメーターの設定、マクロ関数の定義と呼び出し、ファイルのインクルードなど、ロボット モデル ファイルをプログラム可能にする xacro 構文を提案しています。以下は分類の例です:
パラメーターの設定と呼び出し:
// xacro:property设置参数
<xacro:property name="M_PI" value="3.1415926" />
// 引用参数用${}
<origin xyz="0 0 0" rpy="${M_PI/2} 0 0"/>
マクロ関数を設定し、次のように呼び出します。
// xacro:macro设置宏函数,名字是wheel,参数是prefix 和 reflect
<xacro:macro name="wheel" params="prefix reflect">
<joint name="${prefix}_wheel_joint" type="continuous">
<origin xyz="${wheel_joint_x} ${reflect*wheel_joint_y} ${-wheel_joint_z}" rpy="0 0 0" />
<parent link="base_link" />
<child link="${prefix}_wheel_link" />
<axis xyz="0 1 0" />
</joint>
<link name="${prefix}_wheel_link">
<visual>
<origin xyz="0 0 0" rpy="${M_PI/2} 0 0"/>
<geometry>
<cylinder length="${wheel_length}" radius="${wheel_radius}"/>
</geometry>
<material name="white" />
</visual>
</link>
</xacro:macro>
// 调用wheel宏函数
<xacro:wheel prefix="left" reflect="1"/>
<xacro:wheel prefix="right" reflect="-1"/>
ファイルには含まれています
// xacro:include是文件包含,camera.xacro里面定义了一个宏函数
<xacro:include filename="$(find mbot_description)/urdf/sensor/camera.xacro" />
// 调用camera.xacro里面的宏函数
<xacro:usb_camera joint_x="${camera_joint_x}" joint_y="${camera_joint_y}" joint_z="${camera_joint_z}"/>
(2) ここにあるいくつかのファイルは、xacro を使用して上記の mbot_base.urdf を書き換えたものです。具体的な構文については上記の説明を参照してください。
mbot_base.xacro
<?xml version="1.0" ?>
<robot name="mbot" xmlns:xacro="http://www.ros.org/wiki/xacro">
<xacro:property name="M_PI" value="3.1415926" />
<xacro:property name="wheel_joint_x" value="0" />
<xacro:property name="wheel_joint_y" value="0.19" />
<xacro:property name="wheel_joint_z" value="0.05" />
<xacro:property name="wheel_length" value="0.06" />
<xacro:property name="wheel_radius" value="0.06" />
<xacro:property name="caster_joint_x" value="0.18" />
<xacro:property name="caster_joint_y" value="0" />
<xacro:property name="caster_joint_z" value="0.095" />
<xacro:property name="caster_radius" value="0.015" />
<xacro:property name="base_length" value="0.16" />
<xacro:property name="base_radius" value="0.2" />
<xacro:property name="stage_length" value="0.12" />
<xacro:property name="stage_radius" value="0.1" />
<xacro:property name="camera_joint_x" value="0.17" />
<xacro:property name="camera_joint_y" value="0" />
<xacro:property name="camera_joint_z" value="0.1" />
<xacro:property name="kinect_joint_x" value="0.15" />
<xacro:property name="kinect_joint_y" value="0" />
<xacro:property name="kinect_joint_z" value="0.11" />
<xacro:property name="laser_joint_x" value="0" />
<xacro:property name="laser_joint_y" value="0" />
<xacro:property name="laser_joint_z" value="0.085" />
<material name="white">
<color rgba="1 1 1 0.9"/>
</material>
<material name="red">
<color rgba="1 0 0 1"/>
</material>
<material name="grey">
<color rgba="0.5 0.5 0.5 1"/>
</material>
<xacro:macro name="base_stage">
<link name="base_link">
<visual>
<origin xyz="0 0 0" rpy="0 0 0"/>
<geometry>
<cylinder length="${base_length}" radius="${base_radius}"/>
</geometry>
<material name="red" />
</visual>
</link>
<joint name="stage_joint" type="fixed">
<origin xyz="0 0 ${(base_length + stage_length)/2}" rpy="0 0 0" />
<parent link="base_link"/>
<child link="stage_link" />
</joint>
<link name="stage_link">
<visual>
<origin xyz="0 0 0" rpy="0 0 0"/>
<geometry>
<cylinder length="${stage_length}" radius="${stage_radius}"/>
</geometry>
<material name="red" />
</visual>
</link>
</xacro:macro>
<xacro:macro name="wheel" params="prefix reflect">
<joint name="${prefix}_wheel_joint" type="continuous">
<origin xyz="${wheel_joint_x} ${reflect*wheel_joint_y} ${-wheel_joint_z}" rpy="0 0 0" />
<parent link="base_link" />
<child link="${prefix}_wheel_link" />
<axis xyz="0 1 0" />
</joint>
<link name="${prefix}_wheel_link">
<visual>
<origin xyz="0 0 0" rpy="${M_PI/2} 0 0"/>
<geometry>
<cylinder length="${wheel_length}" radius="${wheel_radius}"/>
</geometry>
<material name="white" />
</visual>
</link>
</xacro:macro>
<xacro:macro name="caster" params="prefix reflect">
<joint name="${prefix}_caster_joint" type="continuous">
<origin xyz="${reflect*caster_joint_x} ${caster_joint_y} ${-caster_joint_z}" rpy="0 0 0" />
<parent link="base_link"/>
<child link="${prefix}_caster_link" />
<axis xyz="0 1 0" />
</joint>
<link name="${prefix}_caster_link">
<visual>
<origin xyz="0 0 0" rpy="0 0 0" />
<geometry>
<sphere radius="${caster_radius}" />
</geometry>
<material name="white" />
</visual>
</link>
</xacro:macro>
<xacro:base_stage />
<xacro:wheel prefix="left" reflect="1"/>
<xacro:wheel prefix="right" reflect="-1"/>
<xacro:caster prefix="front" reflect="1"/>
<xacro:caster prefix="back" reflect="-1"/>
<xacro:include filename="$(find mbot_description)/urdf/sensor/camera.xacro" />
<xacro:usb_camera joint_x="${camera_joint_x}" joint_y="${camera_joint_y}" joint_z="${camera_joint_z}"/>
<xacro:include filename="$(find mbot_description)/urdf/sensor/kinect.xacro" />
<xacro:kinect joint_x="${kinect_joint_x}" joint_y="${kinect_joint_y}" joint_z="${kinect_joint_z}"/>
<xacro:include filename="$(find mbot_description)/urdf/sensor/laser.xacro" />
<xacro:laser joint_x="${laser_joint_x}" joint_y="${laser_joint_y}" joint_z="${laser_joint_z}"/>
</robot>
カメラ.xacro
<?xml version="1.0" ?>
<robot name="mbot" xmlns:xacro="http://www.ros.org/wiki/xacro">
<xacro:macro name="usb_camera" params="joint_x joint_y joint_z">
<joint name="camera_joint" type="fixed">
<origin xyz="${-joint_x} ${joint_y} ${joint_z}" rpy="0 0 0" />
<parent link="base_link"/>
<child link="camera_link" />
</joint>
<link name="camera_link">
<visual>
<origin xyz="0 0 0" rpy="0 0 0" />
<geometry>
<box size="0.03 0.04 0.04" />
</geometry>
<material name="grey" />
</visual>
</link>
</xacro:macro>
</robot>
kinect.xacro
<?xml version="1.0" ?>
<robot name="mbot" xmlns:xacro="http://www.ros.org/wiki/xacro">
<xacro:macro name="kinect" params="joint_x joint_y joint_z">
<joint name="kinect_joint" type="fixed">
<origin xyz="${joint_x} ${joint_y} ${joint_z}" rpy="0 0 0" />
<parent link="base_link"/>
<child link="kinect_link" />
</joint>
<link name="kinect_link">
<visual>
<origin xyz="0 0 0" rpy="0 0 1.5708" />
<geometry>
<mesh filename="package://mbot_description/meshes/kinect.dae" />
</geometry>
</visual>
</link>
</xacro:macro>
</robot>
レーザー.xacro
<?xml version="1.0" ?>
<robot name="mbot" xmlns:xacro="http://www.ros.org/wiki/xacro">
<xacro:macro name="laser" params="joint_x joint_y joint_z">
<joint name="laser_joint" type="fixed">
<origin xyz="${joint_x} ${joint_y} ${joint_z}" rpy="0 0 0" />
<parent link="stage_link"/>
<child link="laser_link" />
</joint>
<link name="laser_link">
<visual>
<origin xyz="0 0 0" rpy="0 0 0" />
<geometry>
<cylinder length="0.05" radius="0.05"/>
</geometry>
<material name="grey"/>
</visual>
</link>
</xacro:macro>
</robot>
(3)display_mbot_xacro.launch
<launch>
// 引入xacro的解释器,不然无法读取 .xacro文件
<arg name="model" default="$(find xacro)/xacro '$(find mbot_description)/urdf/mbot_base.xacro'" />
<param name="robot_description" command="$(arg model)" />
<!-- 设置GUI参数,显示关节控制插件 -->
<param name="use_gui" value="true"/>
<!-- 运行joint_state_publisher节点,发布机器人的关节状态 -->
<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" />
<!-- 运行robot_state_publisher节点,发布tf -->
<node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" />
<!-- 运行rviz可视化界面 -->
<node name="rviz" pkg="rviz" type="rviz" args="-d $(find mbot_description)/config/mbot_xacro.rviz" required="true" />
</launch>
(4) ランニング効果は次のとおりです。座標系の軸を示します。
3 まとめ
この記事のコードは私の github: mbot_descriptionでホストされています。