Unified Robot Description Format,簡稱為URDF(標准化機器人描述格式),是一種用於描述機器人及其部分結構、關節、自由度等的XML格式文件。
一、創建第一個URDF文件
將要創建的URDF文件描述的是一種最常見的移動機器人,它有四個輪子、一個帶有抓取器的手臂。
為了打好基礎,我們先做一個帶有四個輪子的機器人底座。在 chapter7_tutorials/robot1_description/urdf 文件夾創建一個新文件並命名為robot1.urdf,其內容如下:
<?xml version="1.0"?>
<robot name="robot1">
<link name="base_link">
<visual>
<geometry>
<box size="0.2 .3 .1"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0.05"/>
<material name="white">
<color rgba="1 1 1 1"/>
</material>
</visual>
</link>
<link name="wheel_1">
<visual>
<geometry>
<cylinder length="0.05" radius="0.05"/>
</geometry>
<origin rpy="0 1.5 0" xyz="0.1 0.1 0"/>
<material name="black">
<color rgba="0 0 0 1"/>
</material>
</visual>
</link>
<link name="wheel_2">
<visual>
<geometry>
<cylinder length="0.05" radius="0.05"/>
</geometry>
<origin rpy="0 1.5 0" xyz="-0.1 0.1 0"/>
<material name="black"/>
</visual>
</link>
<link name="wheel_3">
<visual>
<geometry>
<cylinder length="0.05" radius="0.05"/>
</geometry>
<origin rpy="0 1.5 0" xyz="0.1 -0.1 0"/>
<material name="black"/>
</visual>
</link>
<link name="wheel_4">
<visual>
<geometry>
<cylinder length="0.05" radius="0.05"/>
</geometry>
<origin rpy="0 1.5 0" xyz="-0.1 -0.1 0"/>
<material name="black"/>
</visual>
</link>
<joint name="base_to_wheel1" type="fixed">
<parent link="base_link"/>
<child link="wheel_1"/>
<origin xyz="0 0 0"/>
</joint>
<joint name="base_to_wheel2" type="fixed">
<parent link="base_link"/>
<child link="wheel_2"/>
<origin xyz="0 0 0"/>
</joint>
<joint name="base_to_wheel3" type="fixed">
<parent link="base_link"/>
<child link="wheel_3"/>
<origin xyz="0 0 0"/>
</joint>
<joint name="base_to_wheel4" type="fixed">
<parent link="base_link"/>
<child link="wheel_4"/>
<origin xyz="0 0 0"/>
</joint>
</robot>
二、常見標簽說明
連接(link)標簽
標簽 | 功能 |
---|---|
<link> | 連接的可視化、碰撞和慣性屬性設置 |
<visual> | 設置連接的可視化屬性 |
<collision> | 設置連接的碰撞計算屬性 |
<inertial> | 設置連接的慣性屬性 |
<geometry> | 輸入模型的形狀。提供box、cylinder、sphere等形態 |
<origin> | 設置相對於連接相對坐標系的移動和旋轉 |
<material> | 設置連接的顏色和紋理 |
<mass> | 連接重量(單位:kg)的設置 |
關節(joint)標簽
標簽 | 功能 |
---|---|
<joint> | 與連接的關系和關節類型的設置 |
<parent> | 關節的父連接 |
<child> | 關節的子連接 |
<origin> | 將父連接坐標系轉換為子連接坐標系 |
<axis> | 設置旋轉軸 |
<limit> | 設置關節的速度、力和半徑(僅當關節是revolute或prismatic時) |
transmission標簽
<transmission>是與ROS-CONTROL一起運行所必須的標簽,它輸入關節與舵機之間的命令接口。
標簽 | 功能 |
---|---|
<transmission> | 設置關節和舵機之間的變量 |
<type> | 設置力的傳遞方式的形狀 |
<joint> | 設置關節信息設置 |
<hardwareInterface> | 設置硬件接口 |
<actuator> | 設置舵機信息 |
<mechanicalReduction> | 設置舵機與關節之間的齒輪比 |
注:這里的起點位置是相對與父連桿的位置,並不是絕對坐標。另外連接又稱連桿。
三、解釋文件格式
如你在代碼中所見,有兩種用於描述機器人幾何結構的基本字段:連接(link)和關節(joint)。
第一個連接的名字是base_link(基本連接),這個名字在文件中必須唯一:
<link name="base_link">
<visual>
<geometry>
<box size="0.2 .3 .1"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0.05"/>
<material name="white">
<color rgba="1 1 1 1"/>
</material>
</visual>
</link>
- link name:定義連接名稱為base_link
- visual:讓定義的物體結構可見
- geometry:定義幾何形狀(圓柱體、立方體、球體和網格)為box,尺寸為0.2*0.3*0.1
- origin:rpy-起點位置無位移,xyz-繞z軸旋轉
- material:定義材質(顏色和紋理),這里只定義了顏色為rgba="1 1 1 1"
然后使用以下代碼定義關節:
<joint name="base_to_wheel1" type="fixed">
<parent link="base_link"/>
<child link="wheel_1"/>
<origin xyz="0 0 0"/>
</joint>
- joint name:定義關節名稱為base_to_wheel1,類型為固定關節
- parent link:父連接是base_link
- child link:子連接是wheel_1
- origin:起點位置相對父連接無位移
關節類型
- fiexd:固定關節,不允許運動的特殊關節
- continuous:轉動關節,可以繞單軸無線旋轉
- revolute:旋轉關節,類似於continuous,但旋轉角度有限
- prismatic:滑動關節,沿某一軸線移動的關節,帶有位置極限
- floating:浮動關節,允許進行平移、旋轉運動
- planar:平面關節,允許在平面正交方向上平移或者旋轉
四、檢查URDF語法
ROS為用戶提供了一個檢查URDF語法的命令:
check_urdf robot1.urdf
如果一切正常,將會有如下顯示:
robot name is: Robot1
---------- Successfully Parsed XML ---------------
root Link: base_link has 4 child(ren)
child(1): wheel1
child(2): wheel2
child(3): wheel3
child(4): wheel4
如果你希望以圖形的方式來查看它,那么可以使用urdf_to_graphiz
命令工具:
$ urdf_to_graphiz robot1.urdf
此命令將生成兩個文件:robot1.gv 和 robot1.pdf。可以使用 evince 打開:
evince robot1.pdf
顯示如下:
五、在rviz里查看3D模型
新建launch文件
在robot1_description/launch文件夾下新建display.launch文件,代碼如下:
<?xml version="1.0"?>
<launch>
<arg name="model" />
<arg name="gui" default="False" />
<param name="robot_description" textfile="$(arg model)" />
<param name="use_gui" value="$(arg gui)"/>
<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" ></node>
<node name="robot_state_publisher" pkg="robot_state_publisher" type="state_publisher" />
<node name="rviz" pkg="rviz" type="rviz" args="-d $(find urdf_tutorial)/urdf.rviz" />
</launch>
運行launch文件
$ roslaunch robot1_description display.launch model:="`rospack find robot1_description`/urdf/robot1.urdf"
注:把文件直接拖進終端就可以直接顯示文件位置信息。
顯示如下:
默認狀態下畫面中什么都沒有,此時需要做出調整。在左下角的add按鈕中添加RobotModel,然后將Fixed Frame選為base_link。
六、添加基座臂、連接臂和夾持臂
補充urdf文件
在</robot>前增添以下代碼:
<link name="arm_base">
<visual>
<geometry>
<box size="0.1 .1 .1"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0.1"/>
<material name="white">
<color rgba="1 1 1 1"/>
</material>
</visual>
<collision>
<geometry>
<box size="0.1 .1 .1"/>
</geometry>
</collision>
<inertial>
<mass value="1"/>
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
</inertial>
</link>
<joint name="base_to_arm_base" type="continuous">
<parent link="base_link"/>
<child link="arm_base"/>
<axis xyz="0 0 1"/>
<origin xyz="0 0 0"/>
</joint>
<link name="arm_1">
<visual>
<geometry>
<box size="0.05 .05 0.5"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0.25"/>
<material name="white">
<color rgba="1 1 1 1"/>
</material>
</visual>
<collision>
<geometry>
<box size="0.05 .05 0.5"/>
</geometry>
</collision>
<inertial>
<mass value="1"/>
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
</inertial>
</link>
<joint name="arm_1_to_arm_base" type="revolute">
<parent link="arm_base"/>
<child link="arm_1"/>
<axis xyz="1 0 0"/>
<origin xyz="0 0 0.15"/>
<limit effort ="1000.0" lower="-1.0" upper="1.0" velocity="0.5"/>
</joint>
<link name="arm_2">
<visual>
<geometry>
<box size="0.05 0.05 0.5"/>
</geometry>
<origin rpy="0 0 0" xyz="0.06 0 0.15"/>
<material name="white">
<color rgba="1 1 1 1"/>
</material>
</visual>
<collision>
<geometry>
<box size="0.05 .05 0.5"/>
</geometry>
</collision>
<inertial>
<mass value="1"/>
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
</inertial>
</link>
<joint name="arm_2_to_arm_1" type="revolute">
<parent link="arm_1"/>
<child link="arm_2"/>
<axis xyz="1 0 0"/>
<origin xyz="0.0 0 0.45"/>
<limit effort ="1000.0" lower="-2.5" upper="2.5" velocity="0.5"/>
</joint>
<joint name="left_gripper_joint" type="revolute">
<axis xyz="0 0 1"/>
<limit effort="1000.0" lower="0.0" upper="0.548" velocity="0.5"/>
<origin rpy="0 -1.57 0" xyz="0.06 0 0.4"/>
<parent link="arm_2"/>
<child link="left_gripper"/>
</joint>
<link name="left_gripper">
<visual>
<origin rpy="0 0 0" xyz="0 0 0"/>
<geometry>
<mesh filename="package://pr2_description/meshes/gripper_v0/l_finger.dae"/>
</geometry>
</visual>
<collision>
<geometry>
<box size="0.1 .1 .1"/>
</geometry>
</collision>
<inertial>
<mass value="1"/>
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
</inertial>
</link>
<joint name="left_tip_joint" type="fixed">
<parent link="left_gripper"/>
<child link="left_tip"/>
</joint>
<link name="left_tip">
<visual>
<origin rpy="0.0 0 0" xyz="0.09137 0.00495 0"/>
<geometry>
<mesh filename="package://pr2_description/meshes/gripper_v0/l_finger_tip.dae"/>
</geometry>
</visual>
<collision>
<geometry>
<box size="0.1 .1 .1"/>
</geometry>
</collision>
<inertial>
<mass value="1"/>
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
</inertial>
</link>
<joint name="right_gripper_joint" type="revolute">
<axis xyz="0 0 -1"/>
<limit effort="1000.0" lower="0.0" upper="0.548" velocity="0.5"/>
<origin rpy="0 -1.57 0" xyz="0.06 0 0.4"/>
<parent link="arm_2"/>
<child link="right_gripper"/>
</joint>
<link name="right_gripper">
<visual>
<origin rpy="-3.1415 0 0" xyz="0 0 0"/>
<geometry>
<mesh filename="package://pr2_description/meshes/gripper_v0/l_finger.dae"/>
</geometry>
</visual>
<collision>
<geometry>
<box size="0.1 .1 .1"/>
</geometry>
</collision>
<inertial>
<mass value="1"/>
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
</inertial>
</link>
<joint name="right_tip_joint" type="fixed">
<parent link="right_gripper"/>
<child link="right_tip"/>
</joint>
<link name="right_tip">
<visual>
<origin rpy="-3.1415 0 0" xyz="0.09137 0.00495 0"/>
<geometry>
<mesh filename="package://pr2_description/meshes/gripper_v0/l_finger_tip.dae"/>
</geometry>
</visual>
<collision>
<geometry>
<box size="0.1 .1 .1"/>
</geometry>
</collision>
<inertial>
<mass value="1"/>
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
</inertial>
</link>
運行launch文件
$ roslaunch robot1_description display.launch model:="`rospack find robot1_description`/urdf/robot1.urdf"
顯示如下:
七、使機器人模型運動
最常用的關節是轉動關節。例如,我們在 arm_1_to_arm_base 上使用的就是,其代碼如下所示:
<joint name="arm_1_to_arm_base" type="revolute">
<parent link="arm_base"/>
<child link="arm_1"/>
<axis xyz="1 0 0"/>
<origin xyz="0 0 0.15"/>
<limit effort ="1000.0" lower="-1.0" upper="1.0" velocity="0.5"/>
</joint>
<axis xyz="1 0 0"/>
旋轉轉動軸來運動。- limit 標簽用於選擇以下屬性:effort(關節所承受的最大力),lower(賦值給關節的下限,旋轉關節的單位是弧度,移動關節的單位是米),upper(賦值給關節的上限),velocity(強制關節的最大速度)。
要判斷關節的軸或轉動限值是否合適,有一種好的辦法就是使用 joint_state_publisher GUI 運行 rviz(加上了gui:=true):
$ roslaunch robot1_description display.launch model:="`rospack find robot1_description`/urdf/robot1.urdf" gui:=true
joint_state_publisher GUI 運行界面顯示如下:
urdf文件中每一個axis對應一個調節器,joint_state_publisher應該是ros中自帶的調節joint的功能,所以直接調用就可以。另外界面中的每個滑塊都能控制一個關節。
八、物理屬性和碰撞屬性
如果你想要在 gazebo 或者其他仿真軟件上進行機器人仿真,就需要添加物理屬性和碰撞屬性。這意味着我們需要設定幾何尺寸來計算可能的碰撞,例如設定重量我們才能夠計算慣性等。
你需要保證模型文件中的所有連接都有這些參數,否則就無法對這些機器人進行仿真。
在下面的代碼中,你會看到我們向名為 base_link 的連接添加這兩個屬性:
<link name="base_link">
...
<collision>
<geometry>
<box size="0.2 .3 0.1"/>
</geometry>
</collision>
<inertial>
<mass value="100"/>
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
</inertial>
</link>
對於其他的連接也要這么做。記住,要為所有連接添加 collision 和 inertial 屬性,因為如果你不這樣做的話,gazebo 將無法使用這些模型。
你能夠在 robot1_description/urdf/robot1_physics.urdf 中查看帶有所有參數的完整文件。
參考: