# 8.5 统一机器人描述格式URDF
## 8.5.1 URDF基础
$$\qquad$$URDF(Unified Robot Description Format)统一机器人描述格式,URDF使用XML格式描述机器人文件。URDF语法规范,参考链接:[http://wiki.ros.org/urdf/XML](http://wiki.ros.org/urdf/XML),URDF组件,是由不同的功能包和组件组成:
![](https://img.kancloud.cn/fb/57/fb57efb75110bc59cc3c52d8bfa7f4a7_762x558.png)
$$\qquad$$其中urdf\_parser和urder\_interface已经在hydro之后的版本中去除了。urdf\_paser\_plugin是URDF基础的插件,衍生出了urdfdom(面向URDF文件)和collar\_parser(面向相互文件)。在URDF当中,当你想要描述一个机器人的时候,例如小车的base\_link和右轮right,两个link之间需要joint来连接。参考下图:
$$\qquad \qquad \qquad \qquad \qquad \qquad \qquad \qquad$$![](https://img.kancloud.cn/71/54/715412f4b9db319baded5b308466c4ef_430x511.png)
## 8.5.2 制作URDF模型
$$\quad$$**(1)添加基本模型**
$$\quad$$我们以构建一个小车为例子,为大家讲解这部分的内容:(相关的示例代码可以从我们的tf\_demo中找到),我们的想法是,首先构建base\_link作为小车的父坐标系,然后在base\_link基础上,再构建左轮,右轮 和雷达 link. 最后不同的link之间通过joint来连接。参考代码如下:
$$\quad \quad \quad \quad\quad \quad \quad \quad \quad \quad \quad$$![](https://img.kancloud.cn/81/28/81284b5680a9cc160865aa6db13e1a15_334x272.png)
$$\quad$$小技巧: sudo apt-get install liburdfdom-tools,安装完毕后,执行检查check\_urdf my\_car.urdf如果一切正常,就会有如下显示: ** **
$$\quad \quad \quad \quad\quad \quad \quad \quad \quad \quad \quad$$![](https://img.kancloud.cn/bc/13/bc131f2ca11fd124723769d1c90e6777_336x79.jpg)
$$\quad \quad$$随后打开新的终端,输入roslaunch urdf\_demo display\_urdf\_link\_joint.launch,回车之后,发现所有的link和joint都在一起了,详见urdf本章的demo。
$$\quad \quad \quad \quad\quad \quad \quad \quad \quad \quad \quad\quad \quad \quad \quad \quad$$![](https://img.kancloud.cn/99/b5/99b5f8f2dc71cf0f80b18c03e4791142_189x137.jpg)
$$\quad$$(2)**添加机器人link之间的相对位置关系**
$$\quad$$在基础模型之上,我们需要为机器人之间link来设相对位置和朝向的关系,URDF中通过<origin>来描述这种关系。
$$\quad \quad \quad \quad\quad \quad \quad \quad \quad \quad \quad$$![](https://img.kancloud.cn/56/31/563111021fc9a7e7cf8d6f51bd64a08a_367x316.png)
$$\quad \quad$$随后打开新的终端,输入roslaunch urdf\_demo display\_urdf\_link\_position.launch,回车之后,发现所有的link和joint已经有在固定的位置上了,详见urdf本章的demo。
$$\quad \quad \quad \quad\quad \quad \quad \quad \quad \quad \quad$$![](https://img.kancloud.cn/93/a9/93a9f29532e983e017183d44aa3aacf2_307x181.jpg)
$$\quad$$**(3)添加模型的尺寸,形状和颜色等**
$$\quad$$在已经设置好模型的link基础上,添加模型的形状(例如圆柱或长方体),相对于link的位置,颜色等。其中形状用<geometry>来描述,颜色用<color>来描述。
$$\quad \quad \quad \quad\quad \quad \quad \quad \quad $$![](https://img.kancloud.cn/dc/e6/dce6d793dacf5a5201ad5692dabc437a_414x441.png)
$$\quad$$(4)**显示URDF模型**
$$\quad$$想要在rviz中显示出我们制作好的小车的URDF模型,可以写一个launch文件,参考如下:
$$\quad \quad \quad \quad$$![](https://img.kancloud.cn/54/ac/54ac65d9bce4e9b664a3d4931c147d3a_713x161.png)
$$\quad$$除了launch文件中的前3句,导入我们制作小车的URDF模型外,还需要添加joint\_state\_publisher和robot\_state\_publisjer这两个节点。效果如下:
$$\quad \quad \quad \quad\quad \quad \quad \quad \quad$$![](https://img.kancloud.cn/78/09/7809c426a1d1a7d48645895a8c0c50cd_434x290.png)
$$\quad$$另外,我们可以输入rosrun rqt\_tf\_tree rqt\_tf\_tree,可以看到以下tf 树:
![](https://img.kancloud.cn/a9/60/a960da6a58ee7b482ad8e3374155fd9f_1211x440.png)
$$\quad$$**小技巧:**你可以将launch文件中的param name="use\_gui"的值由false改成true会弹出一个窗口,同一移动进度条,可以临时改变joint的朝向。
$$\quad \quad \quad \quad\quad \quad \quad \quad \quad \quad \quad \quad \quad \quad\quad \quad \quad \quad \quad \quad \quad$$![](https://img.kancloud.cn/c3/5e/c35e180801cfa70b89584f3f0943d94f_156x180.png)
## 8.5.3 制作xacro模型
$$\quad$$什么是Xacro? 我们可以把它理解成为针对URDF的扩展性和配置性而设计的宏语言\(macro language\)。有了Xacro,我们就可以像编程一样来写URDF文件。XACRO格式提供了一些更高级的方式来组织编辑机器人描述. 主要提供了三种方式来使得整个描述文件变得简单。
$$\quad$$**(1)Constants**
```
Usage:<xacro:property name="WIDTH" value="2.0"/>
```
$$\quad$$类似于C语言中的宏定义, 在头部定义后就可以${body\_width}进行引用其数值,有了这个,至少我们可以把需要配置的变量进行统一管理和使用。
$$\quad$$**(2)Macros**
```
Usage:<xacro:macro name="default_origin">
<origin xyz="0 0 0" rpy="0 0 0"/>
</xacro:macro>
<xacro:default_origin />
```
$$\quad$$Macros是xacro文件中最重要的部分. 就像宏函数一样, 完成一些最小模块的定义, 方便重用, 以及可以使用参数来标识不同的部分.
$$\quad$$**(3)Include**
$$\quad$$很多模型都是已宏的形式进行定义, 并以最小集团分成很多个文件. 而最终的机器人描述就变得非常简单了. 下面摘录一个ur5的描述文件. 从中可以看出来xacro的强大优势. 在最后的示例中我们还能够看到, urdf文件也是能够直接导入进来的.
```
Usage:<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="ur5" >
<!-- common stuff -->
<xacro:include filename="$(find ur_description)/urdf/ur5/common.gazebo.xacro" />
<!-- ur5 -->
<xacro:include filename="$(find ur_description)/urdf/ur5/ur5.urdf.xacro" />
<!-- arm -->
<xacro:ur5_robot prefix="" joint_limited="false"/>
<link name="world" />
<joint name="world_joint" type="fixed">
<parent link="world" />
<child link = "base_link" />
<origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
</joint>
</robot>
```
$$\quad$$include类似于C语言中的include, 先将该文件扩展到包含的位置. 但包含进来的文件很有可能只是一个参数宏的定义. 并没有被调用.$$\quad$$
$$\quad$$举例说明打开新的终端,输入roslaunch urdf\_demo display\_xacro.launch,回车之后,发现所有的link和joint已经有在固定的位置上了,并且小车颜色和形状已经固定完成,详见urdf本章的demo。
$$\quad \quad \quad \quad \quad \quad \quad \quad \quad \quad$$![](https://img.kancloud.cn/f5/fb/f5fb2994ceee6fbe2a4ea99de5f80aa7_470x202.jpg)
## 8.5.4 制作gazebo模型
$$\quad$$在已经制作好的xcaro模型的基础上,添加gazebo模型的组建,看起已经变得十分的具有可操作性。对于二轮差动模型通过添加libgazebo\_ros\_diff\_drive.so插件对小车左右轮的控制。
```
<gazebo>
<plugin name="differential_drive_controller" filename="libgazebo_ros_diff_drive.so">
<robotNamespace>/</robotNamespace>
<alwaysOn>true</alwaysOn>
<legacyMode>false</legacyMode>
<updateRate>50</updateRate>
<leftJoint>mybot_left_wheel_hinge</leftJoint>
<rightJoint>mybot_right_wheel_hinge</rightJoint>
<wheelSeparation>${chassisWidth+wheelWidth}</wheelSeparation>
<wheelDiameter>${2*wheelRadius}</wheelDiameter>
<torque>20</torque>
<commandTopic>mybot_cmd_vel</commandTopic>
<odometryTopic>mybot_odom</odometryTopic>
<odometryFrame>odom</odometryFrame>
<robotBaseFrame>mybot_link</robotBaseFrame>
</plugin>
</gazebo>
```
$$\quad$$通过添加libgazebo\_ros\_p3d.so来计算里程。
```
<gazebo>
<plugin name="ground_truth" filename="libgazebo_ros_p3d.so">
<frameName>map</frameName>
<bodyName>mybot_chassis</bodyName>
<topicName>odom</topicName>
<updateRate>30.0</updateRate>
</plugin>
</gazebo>
```
$$\quad$$最后,对gazebo模型中小车左右轮相关PID等参数进行设置
```
<gazebo reference="mybot_chassis">
<material>Gazebo/Orange</material>
</gazebo>
<gazebo reference="caster_wheel">
<mu1>0.0</mu1>
<mu2>0.0</mu2>
<material>Gazebo/Red</material>
</gazebo>
<gazebo reference="right_wheel">
<mu1 value="1.0"/>
<mu2 value="1.0"/>
<kp value="10000000.0" />
<kd value="1.0" />
<fdir1 value="1 0 0"/>
<material>Gazebo/Black</material>
</gazebo>
<gazebo reference="left_wheel">
<mu1 value="1.0"/>
<mu2 value="1.0"/>
<kp value="10000000.0" />
<kd value="1.0" />
<fdir1 value="1 0 0"/>
<material>Gazebo/Black</material>
</gazebo>
</robot>
```
$$\quad$$举例说明打开新的终端,输入roslaunch urdf\_demo display\_gazebo\_rviz.launch,回车之后,发现所有的link和joint已经有在固定的位置上了,并且小车颜色和形状已经固定完成,gazebo界面同样显示正常,详见urdf本章的demo。![](https://img.kancloud.cn/bf/56/bf564493df2111590575a36fb5fa1083_1057x420.jpg)
- 前言
- 第一章 ROS简介
- 机器人时代的到来
- ROS发展历程
- 什么是ROS
- 安装ROS
- 安装ROS-Academy-for-Beginners教学包
- 二进制与源码包
- 安装RoboWare Studio
- 单元测试一
- 第二章 ROS文件系统
- Catkin编译系统
- Catkin工作空间
- Package软件包
- CMakeLists.txt
- package.xml
- Metapacakge软件元包
- 其他常见文件类型
- 单元测试二
- 第三章 ROS通信架构(一)
- Node & Master
- Launch文件
- Topic
- Msg
- 常见msg类型
- 单元测试三
- 第四章 ROS通信架构(二)
- Service
- Srv
- Parameter server
- Action
- 常见srv类型
- 常见action类型
- 单元测试四
- 第五章 常用工具
- Gazebo
- RViz
- Rqt
- Rosbag
- Rosbridge
- moveit!
- 单元测试五
- 第六章 roscpp
- Client Library与roscpp
- 节点初始、关闭与NodeHandle
- Topic in roscpp
- Service in roscpp
- Param in roscpp
- 时钟
- 日志与异常
- 第七章 rospy
- Rospy与主要接口
- Topic in rospy
- Service in rospy
- Param与Time
- 第八章 TF与URDF
- 认识TF
- TF消息
- tf in c++
- tf in python
- 统一机器人描述格式
- 附录:TF数学基础
- 三维空间刚体运动---旋转矩阵
- 三维空间刚体运动---欧拉角
- 三维空间刚体运动---四元数
- 第九章 SLAM
- 地图
- Gmapping
- Karto
- Hector
- 第十章 Navigation
- Navigation Stack
- move_base
- costmap
- Map_server & Amcl
- 附录:Navigation工具包说明
- amcl
- local_base_planner
- carrot_planner
- clear_costmap_recovery
- costmap_2d
- dwa_local_planner
- fake_localization
- global_planner
- map_server
- move_base_msg
- move_base
- move_slow_and_clear
- navfn
- nav_core
- robot_pose_ekf
- rotate_recovery