文章转自 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的更多相关文章
-
ROS机器人程序设计(原书第2版)补充资料 (柒) 第七章 3D建模与仿真 urdf Gazebo V-Rep Webots Morse
ROS机器人程序设计(原书第2版)补充资料 (柒) 第七章 3D建模与仿真 urdf Gazebo V-Rep Webots Morse 书中,大部分出现hydro的地方,直接替换为indigo或ja ...
-
ROS(机器人URDF模型优化)
URDF模型 xacro优化后的URDF模型 1.精简模型代码(创建宏定义,文件包含) 2.提供可编程接口(常量,变量,数学计算,条件语句) 常量定义: name:base_length的值value ...
-
ROS机器人程序设计(原书第2版)补充资料 (拾) 第十章 使用MoveIt!
ROS机器人程序设计(原书第2版)补充资料 (拾) 第十章 使用MoveIt! 书中,大部分出现hydro的地方,直接替换为indigo或jade或kinetic,即可在对应版本中使用. MoveIt ...
-
ROSCon 2016视频和幻灯片发布 ROS机器人操作系统重要参考资料
ROSCon 2016视频和幻灯片发布 By Tully Foote on 十月19,2016 7:28 AM 全部PPT下载地址:http://pan.baidu.com/s/1gf2sn2F RO ...
-
星火计划ROS机器人Spark
星火计划ROS机器人Spark 1 http://wiki.ros.org/Robots/Spark 2 https://github.com/NXROBO/spark ---- Spark Spar ...
-
ros机器人开发概述
1. ROS项目开发流程? 参照古月大神写的ROS探索总结系列:http://blog.exbot.net/archives/619 具体项目设计可看看<程序员>杂志的最新一篇 ...
-
ROS机器人程序设计(原书第2版)补充资料 教学大纲
ROS机器人程序设计(原书第2版) 补充资料 教学大纲 针对该书稍后会补充教学大纲.教案.多媒体课件以及练习题等. <ROS机器人程序设计>课程简介 课程编号:XXXXXX 课程名称:RO ...
-
ROS机器人程序设计(原书第2版)补充资料 (捌) 第八章 导航功能包集入门 navigation
ROS机器人程序设计(原书第2版)补充资料 (捌) 第八章 导航功能包集入门 navigation 书中,大部分出现hydro的地方,直接替换为indigo或jade或kinetic,即可在对应版本中 ...
-
ROS机器人导航一 : 从英雄联盟到ROS导航
写在前面: 这是这个系列的第一篇 本系列主要从零开始深入探索ROS(机器人操作系统)的导航和规划. 这个系列的目标,是让大家了解: 1.ROS的导航是怎么实现的 2.认识ROS里各种已有的导航算法,清 ...
随机推荐
-
centos配置epel
1.下载epel wget http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm 2.安装epel rpm -iv ...
-
android textview段落开头空格问题
textview中段落开头一般都会空2格排版显示,如果靠编辑空格来解决那就大错特错了,完美的解决方法就是用转义字符"\t",在段首加\t\t就解决啦!
-
windows下 定时删除tomcat日志和缓存。可以保留天数
forfiles /p "e:\Program Files\Tomcat 7.0\logs" /s /m *.log /d -5 /c "cmd /c del @path ...
-
【转】.. Android应用内存泄露分析、改善经验总结
原文网址:http://wetest.qq.com/lab/view/107.html?from=ads_test2_qqtips&sessionUserType=BFT.PARAMS.194 ...
-
WebService使用DataSetSurrogate压缩Dataset的序列化和解压反序列化传输 (转)
转自:http://blog.163.com/hehong0925@126/blog/static/1339333372012102242920521/ 在WebService中将dataset序列化 ...
-
配置suricata
yum -y install libpcap libpcap-devel libnet libnet-devel pcre \ pcre-devel gcc gcc-c++ automake auto ...
-
mysql 5.7 启动脚本
最近这段时间,在看mysql,安装了,也应用过,对于生产环境中,一般都选择使用source code安装,在安装的时候可以自定义相关路径和内容,对于生产环境来说更有效.相对于mysql 5.5的安装, ...
-
Git使用五:回到过去
reset:将仓库里面的内容恢复回暂存区,类似于从仓库里检出文件到暂存区checkout:将暂存区的文件恢复回工作区,即,把暂存区的文件检出到工作区 下面是之前三次提交的内容 三个区域的文件状态: 执 ...
-
Android开发 - 更";聪明";的申请权限方式
在Android6.0以后,很多权限需要动态申请,只有在用户点同意后,我们才能使用对应API,因此,正确申请权限就显得很重要. 常用方式 通常我们使用这种方式来判断权限状态: private stat ...
-
论文参考文献中J、M等是什么意思
最近不务正业的写论文,记录下常见的文献标示 国家期刊出版格式要求在中图分类号的下面应标出文献标识码,规定如下: 作者可从下列A.B.C.D.E中选用一种标识码来揭示文章的性质: A—理论与应用研究学术 ...