文章转自 https://blog.csdn.net/sunbibei/article/details/52297524 特此鸣谢原创作者的辛勤付出

1 URDF 文件

1.1 link和joint

图中机器人的描述方式

<robot name="test_robot">
<link name="link1" />
<link name="link2" />
<link name="link3" />
<link name="link4" /> <joint name="joint1" type="continuous">
<parent link="link1"/>
<child link="link2"/>
</joint> <joint name="joint2" type="continuous">
<parent link="link1"/>
<child link="link3"/>
</joint> <joint name="joint3" type="continuous">
<parent link="link3"/>
<child link="link4"/>
</joint>
</robot>

以上描述只能够描述机器人的大致样子,不能够确定link的位置关系和具体形状。

1.2 位置

在定义好了机器人的骨架后, 进一步我们可以使用origin子标签进行定义link所应该在的位置. 但是有一点应该注意到, link和link之间是使用joint进行连接, 那么link的位置, 就由连接他的joint确定. 所以, 该子标签是定义在joint内. 在三维空间中, 要精确描述一个刚性体的姿态, 仅仅使用他的xyz坐标是不够的, 还需要使用rpy. rpy角是描述船舶在海中航行时姿态的一种方法. 将船的行驶方向取为z轴, 绕z轴旋转称为滚动(Roll), 绕y轴旋转称为俯仰(Pitch), 绕x轴旋转称为偏转(Yaw). 这种描述方式大量运用于各个领域. 依稀记得, kinect2关于脸部模型匹配的DEMO程序里面, 对脸部的描述就用到了这种描述方式来描述姿态. 在机器人中, 当然运用就更多了. 现在对之前的内容进行扩充. 其中rpy代表的是角度, 用弧度表示.

<robot name="test_robot">
<link name="link1" />
<link name="link2" />
<link name="link3" />
<link name="link4" /> <joint name="joint1" type="continuous">
<parent link="link1"/>
<child link="link2"/>
<origin xyz=".5 .3 0.7" rpy="0 0 0" />
</joint> <joint name="joint2" type="continuous">
<parent link="link1"/>
<child link="link3"/>
<origin xyz="-.2 .5 -0.3" rpy="0 0 1.57" />
</joint> <joint name="joint3" type="continuous">
<parent link="link3"/>
<child link="link4"/>
<origin xyz=".5 0 0.2" rpy="0 0 -1.57" />
</joint>
</robot>

上述位置关系定义如下图所示. xyz就如同一个平移向量, 将下一个link的原点坐标移动到下一个位置(起点是父link的原点). 同时, 你也可以多尝试几次rpy, 体会下一个坐标系是如何进行变换的. 虽然现在还没有任何东西出来, 但每个link的空间位置以及姿态已经被我们所指定了.

1.3 形状

<?xml version="1.0"?>
<robot name="test_robot">
<link name="link1">
<visual>
<geometry>
<cylinder length="0.6" radius="0.2" />
</geometry>
</visual>
</link> <link name="link2">
<visual>
<geometry>
<box size="0.6 0.2 .1" />
</geometry>
</visual>
</link> <link name="link3" >
<visual>
<geometry>
<sphere radius="0.2"/>
</geometry>
</visual>
</link> <link name="link4" >
<visual>
<origin rpy="0 -1.57 0" xyz="0 0 0"/>
<geometry>
<mesh filename="package://urdf_csdn/urdf/mesh/knife.stl"/>
</geometry>
</visual>
</link> <joint name="joint1" type="fixed">
<parent link="link1"/>
<child link="link2"/>
<origin xyz="0.22 0 0.6" rpy="0 1.57 0" />
</joint> <joint name="joint2" type="continuous">
<parent link="link1"/>
<child link="link3"/>
<origin xyz="-0.1 0.5 0" />
</joint> <joint name="joint3" type="fixed">
<parent link="link3"/>
<child link="link4"/>
<origin xyz=".5 0 0" rpy="0 0 -1.57" />
</joint>
</robot>

1.4 Collision和joint limit

当然, 每个link一般是不会产生重合的, 在运动规划的时候, 也会去避免碰撞到自己, 所以针对于每一个link, 还有一个collision标签, 和visual标签内容完全一样.

前面内容可以看到, 每个link可以看作是一个刚体, 刚体和刚体之间是通过joint进行连接, 那么, 问题就来了. 这个joint是固定的? 还是可以任意的动? 如果可以动, 那么, 问题又来了, 极限位置是多少? 等等等等…

比如, 我们限定joint2只能沿着y轴旋转, 则需要添加 <axis xyz="0 1 0"/> , 类似的, 可以指定其他关节的转动轴, 例如 <axis xyz="-0.2 0.1 1"/> .

比如, 我们要限定joint2的移动范围, 则需要添加<limit lower="-3.14" upper="3.14" effort="150.0" velocity="3.15"/>, 从标签中可以看到, 上下限以及速度, 力矩等都是可以指定的.

<?xml version="1.0"?>
<robot name="test_robot">
<link name="link1">
<visual>
<geometry>
<cylinder length="0.6" radius="0.2" />
</geometry>
</visual> <collision>
<origin xyz="0.0 0 0.0" rpy="0 0 0" />
<geometry>
<cylinder length="0.6" radius="0.2" />
</geometry>
</collision>
</link> <link name="link2">
<visual>
<geometry>
<box size="0.6 0.2 .1" />
</geometry>
</visual>
</link> <link name="link3" >
<visual>
<geometry>
<sphere radius="0.2"/>
</geometry>
</visual>
</link> <link name="link4" >
<visual>
<origin rpy="0 -1.57 0" xyz="0 0 0"/>
<geometry>
<mesh filename="package://urdf_csdn/urdf/mesh/knife.stl"/>
</geometry>
</visual>
</link> <joint name="joint1" type="fixed">
<parent link="link1"/>
<child link="link2"/>
<origin xyz="0.22 0 0.6" rpy="0 1.57 0" />
</joint> <joint name="joint2" type="continuous">
<parent link="link1"/>
<child link="link3"/>
<origin xyz="-0.1 0.5 0" />
<axis xyz="0 1 0"/>
<limit lower="-3.14" upper="3.14" effort="150.0" velocity="3.15"/>
</joint> <joint name="joint3" type="fixed">
<parent link="link3"/>
<child link="link4"/>
<origin xyz=".5 0 0" rpy="0 0 -1.57" />
</joint>
</robot>

1.5 可视化

查看urdf文件, 可以使用urdf_tutorial包, 命令格式roslaunch urdf_tutorial display.launch model:=path/to/your/xxx.urdf, 会使用Rviz进行显示, 如上述内容, 进行显示之后, 可以得到下图所示内容. 坐标系图示, 需要添加TF条目进行显示. 值得注意的地方, 将Global Options中的fixed frame设定为link1. 如果你设定了可移动的关节, 想查看以下关节移动的效果以及设定等, 使用roslaunch urdf_tutorial display.launch model:=path/to/your/xxx.urdf gui:=true, 你会看到弹出一个控制面板(如果没找到, 再好好找一找, 或许真的很小).

通过上述方式, 在rviz中正确显示模型之后, 新打开一个命令行, 输入rostopic list命令, 可以查看到类似如下的输出. 可以看到, 开启了/joint_states话题(Topic), 使用rostopic echo /joint_states可以看到话题数据

2 XACRO文件

前面也提到了, XACRO文件和URDF实质上是等价的. XACRO格式提供了一些更高级的方式来组织编辑机器人描述. 主要提供了三种方式来使得整个描述文件变得简单. 借用在教程中一句话来形容xacro的优势: “Fortunately, you can use the xacro package to make your life simpler”.

2.1 Constants

Usage:  <xacro:property name="WIDTH" value="2.0"/>

类似于C语言中的宏定义, 在头部定义, 如 <xacro:property name="WIDTH" value="2.0"/> , 以 ${WIDTH} 的方式进行使用. 经常会看到的一个常量定义,  <property name="PI" value="3.14159265" /> . 还有定义一个前缀, 这样后面关节名都可以方便的进行修改. 比如 <property name="prefix" value="my_"/> , 后面关节名字就可以类似的进行更新.  <joint name="${prefix}joint1" type="revolute"/>.

在有了上面的常量定义之后, 类似于宏定义, 完成字符串替换, 同时还可以进行一些简单的数学运算.

Usage:  ${1/2} ,  ${PI*(WIDTH*0.5)} 

2.2 Macros

这个才是xacro文件中最重要的部分. 就像宏函数一样, 完成一些最小模块的定义, 方便重用, 以及可以使用参数来标识不同的部分.

2.2.1 Simple Macro

Usage

<xacro:macro name="default_origin">
<origin xyz="0 0 0" rpy="0 0 0"/>
</xacro:macro>
<xacro:default_origin />

前面三行对宏进行定义, 第四行是使用.

2.2.2 Paramiterized Macro

Usage

<xacro:macro name="default_link" params="prefix">
<link name="${prefix}_link1" />
</xacro:macro>
<xacro:default_link prefix="my" />

类似, 前三行定义, 第四行是进行使用. 当然, 不单由这样简单的参数, 还可以使用块参数.

Usage

<xacro:macro name="default_link" params="prefix *origin">
<link name="${prefix}_link1" >
<xacro:insert_block name="prigin" />
</link>
</xacro:macro>
<xacro:default_link prefix="my">
<origin xyz="0 0 0" rpy="0 0 0" />
</xacro:default_link>

一般情况下, 很多已有的机器人模型, 都是以xacro格式提供描述, 而在xacro文件中, 整个机器人定义为一个很大的宏. 例如, barrett hand, 想进一步了解的朋友可以点击前面的链接, 查看以下barrett hand是如何进行描述的

2.2.3 Include

很多模型都是已宏的形式进行定义, 并以最小集团分成很多个文件. 而最终的机器人描述就变得非常简单了. 下面摘录一个ur5的描述文件. 从中可以看出来xacro的强大优势. 在最后的示例中我们还能够看到, urdf文件也是能够直接导入进来的.

<?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>

当然, 此时的简单是建立在之前的复杂的基础上的. 从上述内容中可以看到, 首先是在ur_description包中找到另外几个xacro文件, 将其包含进来. 当然应该注意到, include类似于C语言中的include, 先将该文件扩展到包含的位置. 但包含进来的文件很有可能只是一个参数宏的定义. 并没有被调用. 所以, 示例中调用了一个宏(<xacro:ur5_robot prefix="" joint_limited="false"/>), 产生一个ur5机器人

2.3 可视化

urdf_tutorial包也是可以查看xacro文件的. 使用

roslaunch urdf_tutorial xacrodisplay.launch model:=path/to/your/xxx.urdf.xacro.

3 关于urdf_tutorial

前面提到的可视化都是使用urdf_tutorial包进行的. 分别调用了两个launch文件. 在上面的示例中我们还看到了不但会使用rviz进行可视化, 还会发起一些话题等. 其实这些我们能够从他的launch文件中一窥究竟.

打开命令行, 输入: rosed urdf_tutorial dispaly.launch. 会使用vim打开该文件. 可以看到下述内容

<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 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" required="true" />
</launch>

由上可以看到, 参数model是没有默认值的, 所以调用该launch文件必须指定model参数. 其他都比较易懂, 主要解释以下robot_description, 可以看到, 其前面是param. 这个是指定ros 参数服务器中的参数值. 而打开rviz之后, rviz就是直接从参数服务器中读取机器人描述文件, 也就是这个参数. 然后进行显示. use_gui也是如此对显示产生的影响. 另外, 还发起了两个发布者节点, 分别发布joint_states和robot_state. 这也就是会由joint_states话题的原因. xacrodispaly.launch文件和上面类似, 但在处理文件时, 使用的是:  <param name="robot_description" command="$(find xacro)/xacro.py $(arg model)" /> . 在launch中将xacro文件解析为urdf.

至于其中启动的两个节点, joint_state_publisher 和 robot_state_publisher, 可以查看ROS Answer上相关的解释. 另外, 在robot_state_publisher概述中提到, robot_state_publisher从 /joint_states 话题中获取机器人joint角度作为输入, 使用机器人的运动学树模型计算出机器人link的3D姿态, 然后将其发布到话题 /tf 和  /tf_static . joint_state_publisher从ROS参数服务器中读取robot_description参数, 找到所有non-fixed joint, 发布他们的 JointState 消息到 /joint_states 话题

<ROS> 机器人描述--URDF和XACRO的更多相关文章

  1. ROS机器人程序设计(原书第2版)补充资料 (柒) 第七章 3D建模与仿真 urdf Gazebo V-Rep Webots Morse

    ROS机器人程序设计(原书第2版)补充资料 (柒) 第七章 3D建模与仿真 urdf Gazebo V-Rep Webots Morse 书中,大部分出现hydro的地方,直接替换为indigo或ja ...

  2. ROS(机器人URDF模型优化)

    URDF模型 xacro优化后的URDF模型 1.精简模型代码(创建宏定义,文件包含) 2.提供可编程接口(常量,变量,数学计算,条件语句) 常量定义: name:base_length的值value ...

  3. ROS机器人程序设计(原书第2版)补充资料 (拾) 第十章 使用MoveIt!

    ROS机器人程序设计(原书第2版)补充资料 (拾) 第十章 使用MoveIt! 书中,大部分出现hydro的地方,直接替换为indigo或jade或kinetic,即可在对应版本中使用. MoveIt ...

  4. ROSCon 2016视频和幻灯片发布 ROS机器人操作系统重要参考资料

    ROSCon 2016视频和幻灯片发布 By Tully Foote on 十月19,2016 7:28 AM 全部PPT下载地址:http://pan.baidu.com/s/1gf2sn2F RO ...

  5. 星火计划ROS机器人Spark

    星火计划ROS机器人Spark 1 http://wiki.ros.org/Robots/Spark 2 https://github.com/NXROBO/spark ---- Spark Spar ...

  6. ros机器人开发概述

    1.       ROS项目开发流程? 参照古月大神写的ROS探索总结系列:http://blog.exbot.net/archives/619 具体项目设计可看看<程序员>杂志的最新一篇 ...

  7. ROS机器人程序设计(原书第2版)补充资料 教学大纲

    ROS机器人程序设计(原书第2版) 补充资料 教学大纲 针对该书稍后会补充教学大纲.教案.多媒体课件以及练习题等. <ROS机器人程序设计>课程简介 课程编号:XXXXXX 课程名称:RO ...

  8. ROS机器人程序设计(原书第2版)补充资料 (捌) 第八章 导航功能包集入门 navigation

    ROS机器人程序设计(原书第2版)补充资料 (捌) 第八章 导航功能包集入门 navigation 书中,大部分出现hydro的地方,直接替换为indigo或jade或kinetic,即可在对应版本中 ...

  9. ROS机器人导航一 : 从英雄联盟到ROS导航

    写在前面: 这是这个系列的第一篇 本系列主要从零开始深入探索ROS(机器人操作系统)的导航和规划. 这个系列的目标,是让大家了解: 1.ROS的导航是怎么实现的 2.认识ROS里各种已有的导航算法,清 ...

随机推荐

  1. git项目远程地址修改后本地如何处理

    今天运维人员为了方便管理,将远程的项目地址给迁移了, 原来是 git@git.lalala.com:yuanlaide/happy.git 变成了 git@git.lalala.com:houlaid ...

  2. 画一条0.5px的线

    通过伪类元素:after为其添加样式,用transform:scaleY令其在垂直方向缩小0.5倍 .div:after{ height: 1px; transform: scaleY(0.5); t ...

  3. 【C/C++】内存基础

    1. 基本数据类型 short s = 0x4142; // 16进制 char c = *(char*)&s; cout << c << endl; 我的电脑上输出为 ...

  4. Android动画-View动画

    View动画 Android动画分为三类:View动画,帧动画,和属性动画.帧动画也是View动画的一种. View动画的作用对象是View,之所以强调这一点是因为其作用对象有别于Android的另一 ...

  5. Sonya and Robots(CodeForces 1004C)

    Since Sonya is interested in robotics too, she decided to construct robots that will read and recogn ...

  6. linux的简单操作和安装

    1.学习linux,安装的方式在你的windows上安装一个 vmware虚拟化软件(基于它可以安装各种系统) 2.公司中 会提供一个云服务器给你用 服务器ip 123.206.16.61 公网ip账 ...

  7. Mysql服务配置优化

    mysql服务器优化包含 硬件优化.操作系统配置优化(cpu调度.网络.内存.虚拟内存.磁盘io).Mysql服务配置优化(最大连接数.表缓存等.存储引擎).表结构优化.索引优化 总共5个方面. 本片 ...

  8. 第三视角Beta答辩总结

    第三视角Beta答辩总结 博客链接以及团队信息 组长博客链接 成员信息(按拼音排序) 姓名 学号 备注 张扬 031602345 组长 陈加伟 031602204 郭俊彦 031602213 洪泽波 ...

  9. CodeForces - 589B(暴力+排序)

    Dasha decided to bake a big and tasty layer cake. In order to do that she went shopping and bought n ...

  10. linux之目录知识

    /var 目录下的路径知识: /var/log    记录系统及软件运行信息文件所在目录 /var/log/messages 系统级别日志文件 /var/log/secure 用户登录信息日志文件 / ...