当前位置: 代码迷 >> 综合 >> xacro——urdf文件的优美进化!
  详细解决方案

xacro——urdf文件的优美进化!

热度:27   发布时间:2024-01-29 05:33:26.0

xacro——urdf的优美进化!

  • 1.What:什么是xacro?
  • 2.Why: 为什么要使用xacro?
    • 2.1 两者的区别
    • 2.2 xacro的优势
  • 3.How: 怎么使用xacro?
    • 3.1 ·常量定义/使用·数学计算·宏定义/使用·文件包含
    • 3.1 条件语句

1.What:什么是xacro?

根据 ROS wiki 的定义,

Xacro (XML Macros) Xacro is an XML macro language. With xacro, you can construct shorter and more readable XML files by using macros that expand to larger XML expressions.>
“Xacro是一种 XML宏语言。使用xacro,您可以使用扩展到更大的XML表达式的宏来构造更短、更可读的XML文件。”

而我们在这里要说的xacro文件,其实就是运用xacro语言来描述机器人模型的一种文件,从本质上来说,和 urdf文件 并无区别。更进一步来说,xacro文件其实就是urdf文件的升级版。

2.Why: 为什么要使用xacro?

2.1 两者的区别

前面我们提到,xacro其实就是urdf的升级版。因此,xacro就是建立在urdf的基础上进行扩充,只要urdf能做到的,xacro通通都能实现;而urdf做不到 宏定义、文件包含、条件判断等等的功能,xacro也都能做到!

2.2 xacro的优势

对比urdf,我们能大致总结出xacro的功能:

精简模型代码
1、创建宏定义
2、文件包含
提供可编程接口
1、常量
2、变量
3、数学计算
4、条件语句

所以显而易见,当我们的模型文件较为复杂,重复冗余的部分较多的时候,我们可以通过宏定义和定义常量、变量的方法大幅度降低模型文件的复杂度。比方说,模型的描述对象是一个小车,而小车的四个轮子轮廓都一样,如果我们使用urdf文件来描述的话,就需要4个轮子的tag一个一个的具体参数全部列出来;而如果我们使用xacro的话,我们只需要定一个描述轮子的宏模板,再根据传入的不同参数分别进行4次调用,就可以描述出完整的小车。
另外,如果用到的模型涉及到多次不同环境下的调用的时候,urdf是需要建立多个不同的urdf文件来一一应对这些不同环境;而xacro,只需要结合到变量和条件语句的运用,就可以仅仅通过单单一个xacro文件来应对各种环境。

3.How: 怎么使用xacro?

上面多次提到了xacro是urdf的进化版,所以,如果说 模型完全不需要用上xacro扩展出来的新功能 ,那我们只需要把文件名的后缀从 .urdf 变更为 .xacro ,然后将在开头的

<robot name="your_robot_description">

变更为:

<robot name="your_robot_description" xmlns:xacro="http://www.ros.org/wiki/xacro">

这样,我们就完成从urdf到xacro的优美进化拉!

下面,我就来简单介绍下xacro这些扩展功能是如何使用吧!

3.1 ·常量定义/使用·数学计算·宏定义/使用·文件包含

其实这些基础功能,在官方给出的wiki里面都有详细的介绍。但是我觉得有点地方可能说的不太清晰,因此我更推荐另外一个CSDN博主写的教程,我就不拾人牙慧了。

链接: UDRF优化—XACRO.

从常量定义一直到xacro文件调用到实例,都写得很清楚,非常建议大家去看一看。
我这里再另外对条件语句这个功能单独介绍一下。

3.1 条件语句

前面有说到,当我们使用一个xacro文件来应对多个不同的环境时,就是条件语句大显身手的时刻了!大致的思路就是,在xacro文件中加入xacro:if语句块

<xacro:if value="<expression>"><... some xml code here ...>
</xacro:if>

然后,在launch文件中调用xacro文件时,从launch文件中往xacro文件传入“expression”变量,来实现在不同环境下对不同模块的调用。
这部分的功能实现其实已经有人在rosanswer上提问过,英文好的同学可以直接点进这里来看一下。下面我也会再详细的介绍一下。

·首先是我们启动xacro文件的launch文件

<?xml version="1.0"?>
<launch><arg name="temp" default="true" /><param name="robot_description" command="$(find xacro)/xacro'$(find xacro)/xacro '$(find your_pkg)/your_pwd/yourfile.xacro'prefix:=$(arg temp)"/>
</launch>

其中,第一句

<arg name="temp" default="true" />

在将变量从launch传入xacro文件前,我们必须要定义好这个变量以及他的初始值(跟C语言a=1前必须先int a的概念类似)。
然后是第二句,前半句就是定义需要打开的xacro文件,而后半句就是我们需要关注到的点

<param name=.... comand="....    prefix:=$(arg temp)">

这句跟在$(find pkg)后面的话,就是将我们前面定义好的temp变量传入到xacro中的prefix变量中。当我们不对launch中的temp变量作改动时,在launch启动时,我们给temp定义的初始值(default)将会传入xacro的prefix中,若< arg name=“temp” default=“true” /> 则xacro中的prefix值就为true,如果default=“0”,则prefix值就为0。

·然后就是我们通过launch来启动的xacro文件
将需要进行条件判定的语句,填入xacro:if的程序段中,例如我下面的link "world"和include

<?xml version="1.0"?>
<robot name="my_arm" xmlns:xacro="http://www.ros.org/wiki/xacro"><xacro:arg name="prefix" default="0"/><xacro:if value="$(arg prefix)"><xacro:include filename="$(find my_arm_description)/urdf/xacro/my_arm_gazebo.gazebo" /> <!-- Used for fixing robot to Gazebo 'base_link' --><link name = "world"/><joint name="base_joint" type="fixed"><parent link="world"/><child link="base_link"/></joint>
</xacro:if>another robot description.....
</robot>

跟launch文件一样,在使用传入的perfix变量前,也需要先对变量进行定义

<xacro:arg name="prefix" default="0"/>

这里的变量名也不一定是“prefix”,反正只需要跟launch文件中“:=”前定义的变量名一致即可。如果外部的launch文件在调用xacro时,没有传入变量,那么prefix的值就等于在xacro定义的defaut值,如果传入了,就等于launch传入的值。

<xacro:if value="$(arg prefix)">...
</xacro:if>

这部分就是,如果prefix的值为"true"或者"1"则执行(疑似不为"0"的值都可以),里面的代码块就会被执行。里面可以填入其他需要加入条件判断任何xml语句。若prefix的值为"false"或者"0",则跳过该代码段。
条件语句的简单使用大概就是如此。如果大家还有兴趣继续深入的话,可以看一下xacro github源码上的issue区,会有不少让人耳目一新的用法~

链接: link.