[ROS 系列学习教程] 建模与仿真 - Xacro 语法

在这里插入图片描述

ROS 系列学习教程(总目录)

本文目录

  • 一、属性与属性块
  • 二、数学表达式
  • 三、宏
    • 3.1 宏的基本使用
    • 3.2 属性块做为宏的入参
    • 3.3 任意数量元素做为宏的入参
    • 3.4 指定多个块元素的处理顺序
    • 3.5 宏嵌套
    • 3.6 默认参数
    • 3.7 局部属性
  • 四、Rospack 命令
  • 五、包含其他 xacro 文件
  • 六、条件语句
  • 七、YAML 支持
  • 八、从 CMakeLists.txt 构建
  • 九、处理顺序
  • 十、调试语法错误

可以发现 urdf 不支持模块化编程,无法实现代码复用,也不支持数学计算, 代码可读性及复用性非常差,效率极低。

为了解决这一问题,ROS提供了 Xacro ,它是 XML Macros 的缩写,即 XML 宏,是可编程的 XML,支持使用变量、函数、数学公式计算、条件/循环流程控制等。

使用 Xacro 时,根标签 robot 中必须包含命名空间声明 xmlns:xacro = "http://wiki.ros.org/xacro"

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

一、属性与属性块

属性可以理解为变量,属性块可以理解为结构体。

属性示例,将会一个圆柱体的半径和高封装到变量里:

<!-- 定义属性 -->
<xacro:property name="the_radius" value="2.1" />
<xacro:property name="the_length" value="4.5" /><!-- 调用属性 -->
<geometry type="cylinder" radius="${the_radius}" length="${the_length}" />

同样,可以使用属性块封装一个实体,在需要的地方调用:

<!-- 定义属性块 -->
<xacro:property name="front_left_origin"><origin xyz="0.3 0 0" rpy="0 0 0" />
</xacro:property><pr2_wheel name="front_left_wheel"><!-- 调用属性块 --><xacro:insert_block name="front_left_origin" />
</pr2_wheel>

二、数学表达式

Xacro支持基本的数学表达式运算,格式如下:

${ 数学表达式 }

示例如下:

<xacro:property name="radius" value="4.3" />
<circle diameter="${2 * radius}" />

在ROS Jade版本中,Xacro引入了python解析数学表达式,所以,Xacro数学表达式中可以使用Python math包中的函数与常量。示例如下:

<xacro:property name="R" value="2" />
<xacro:property name="alpha" value="${30/180*pi}" />
<circle circumference="${2 * pi * R}" pos="${sin(alpha)} ${cos(alpha)}" />
<limit lower="${radians(-90)}" upper="${radians(90)}" effort="0" velocity="${radians(75)}" />

三、宏

Xacro 宏可以理解为函数,目的是提高代码复用率,优化代码结构,提高安全性。

使用 macro 标记定义宏,并指定宏名称和参数列表,参数列表应以空格分隔。

3.1 宏的基本使用

<!-- 定义宏 -->
<xacro:macro name="add_wheels" params="name flag"><link name="${name}_wheel"><visual><geometry><cylinder radius="${wheel_radius}" length="${wheel_length}" /></geometry><origin xyz="0.0 0.0 0.0" rpy="${PI / 2} 0.0 0.0" /><material name="black" /></visual></link><joint name="${name}_wheel2base_link" type="continuous"><parent link="base_link" /><child link="${name}_wheel" /><origin xyz="0 ${flag * base_link_radius} ${-(earth_space + base_link_length / 2 - wheel_radius) }" /><axis xyz="0 1 0" /></joint>
</xacro:macro><!-- 调用宏 -->
<xacro:add_wheels name="left" flag="1" />
<xacro:add_wheels name="right" flag="-1" />

该实例定义了一个 add_wheels 的宏,它接受两个参数: nameflag ,分别是轮子的名字和方向。

3.2 属性块做为宏的入参

<!-- 定义宏 -->
<xacro:macro name="pr2_caster" params="suffix *origin"><joint name="caster_${suffix}_joint"><axis xyz="0 0 1" /></joint><link name="caster_${suffix}"><xacro:insert_block name="origin" /></link>
</xacro:macro><!-- 调用宏 -->
<xacro:pr2_caster suffix="front_left"><pose xyz="0 1 0" rpy="0 0 0" />
</xacro:pr2_caster>

该示例声明了一个宏 pr2_caster,它接受两个参数: suffixorigin。请注意, origin* 。这表明 origin 是一个块参数。调用时在子级标签中声名块参数,多个块参数时,按插入顺序处理,如下:

<!-- 定义宏 -->
<xacro:macro name="pr2_caster" params="suffix *origin *color *mass"><joint name="caster_${suffix}_joint"><axis xyz="0 0 1" /></joint><link name="caster_${suffix}"><xacro:insert_block name="origin" />        <xacro:insert_block name="color" />        <xacro:insert_block name="mass" /></link>
</xacro:macro><!-- 调用宏 -->
<xacro:pr2_caster suffix="front_left"><pose xyz="0 1 0" rpy="0 0 0" /> <!-- origin --><color name="yellow"/> <!-- color --><mass>0.1</mass> <!-- mass -->
</xacro:pr2_caster>

3.3 任意数量元素做为宏的入参

<!-- 定义宏 -->
<xacro:macro name="pr2_caster" params="suffix *origin **content **anothercontent"><joint name="caster_${suffix}_joint"><axis xyz="0 0 1" /></joint><link name="caster_${suffix}"><xacro:insert_block name="origin" /><xacro:insert_block name="content" /><xacro:insert_block name="anothercontent" /></link>
</xacro:macro><!-- 调用宏 -->
<xacro:pr2_caster suffix="front_left"><!-- origin --><pose xyz="0 1 0" rpy="0 0 0" /><!-- content --><container><color name="yellow"/><mass>0.1</mass></container><!-- anothercontent --><another><inertial><origin xyz="0 0 0.5" rpy="0 0 0"/><mass value="1"/><inertia ixx="100"  ixy="0"  ixz="0" iyy="100" iyz="0" izz="100" /></inertial></another>
</xacro:pr2_caster>

该示例声明了一个宏 pr2_caster,除了前文讲到的参数 suffixorigin,还有contentanothercontent,他们前面都带**,表明他们允许插入任意数量的元素。按照块元素插入顺序,他们分别为 containeranother,在他们的子级可以插入任意数量的元素。

3.4 指定多个块元素的处理顺序

上文宏定义中 xacro:insert_block 用于指定插入的块元素,插入的顺序即处理顺序

<!-- 定义宏 -->
<xacro:macro name="reorder" params="*first *second"><xacro:insert_block name="second"/><xacro:insert_block name="first"/>
</xacro:macro><!-- 调用宏 -->
<xacro:reorder><first/><second/>
</xacro:reorder>

处理顺序为 second -> first

3.5 宏嵌套

宏嵌套即一个宏内调用其他宏,这种宏在被调用时,各宏从外部到内部依次处理。

<!-- 定义宏 foo -->
<xacro:macro name="foo" params="x"><in_foo the_x="${x}" />
</xacro:macro><!-- 定义宏 bar -->
<xacro:macro name="bar" params="y"><in_bar><xacro:foo x="${y}" /></in_bar>
</xacro:macro><!-- 调用宏 bar -->
<xacro:bar y="12" />

调用宏bar并传入12,先展开宏bar,再展开宏foo,如下:

<in_bar><in_foo the_x="12" />
</in_bar>

3.6 默认参数

宏的入参可以有默认值,如下使用海象运算符 :=

<xacro:macro name="foo" params="x:=${x} y:=${2*y} z:=0"/>

如果默认值包含表达式,则它们将在实例化时进行计算。

<xacro:macro name="foo" params="p1 p2:=expr_a p3:=^ p4:=^|expr_b">

符号 ^ 表示使用外部属性的值(具有相同名称)。管道 | 表示如果属性未在外部范围中定义,则使用给定的后备值。

3.7 局部属性

在宏中定义的属性和宏是该宏的局部属性和宏,即在外部不可见。使用可选字段 scope="parent | global",可以将属性定义导出到宏的父范围(或全局范围)。

四、Rospack 命令

Xacro 允许使用某些 rospack 命令:

<foo value="$(find xacro)" />
<foo value="$(arg myvar)" />

五、包含其他 xacro 文件

可以使用 xacro:include 标签包含其他 xacro 文件:

<xacro:include filename="$(find package)/other_file.xacro" />
<xacro:include filename="other_file.xacro" />
<xacro:include filename="$(cwd)/other_file.xacro" />

为了避免各个包含文件的属性和宏之间发生名称冲突,可以为包含的文件指定命名空间 - 提供属性 ns:

<xacro:include filename="other_file.xacro" ns="namespace"/>

通过在前面添加命名空间(用点分隔)可以访问命名空间的宏和属性:

${namespace.property}

六、条件语句

Xacro同样支持条件语句,示例如下:

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

其中 <expression> 表达式的结果必须是 01falsetrue ,否则会报错。

在 ROS Jade 版本中,Xacro引入了python解析表达式,所以,任何计算结果为布尔值的 Python 表达式都是合法的。

<xacro:property name="var" value="useit"/>
<xacro:if value="${var == 'useit'}"/>
<xacro:if value="${var.startswith('use') and var.endswith('it')}"/><xacro:property name="allowed" value="${[1,2,3]}"/>
<xacro:if value="${1 in allowed}"/>

七、YAML 支持

属性也可以是字典或列表 - 使用 python 语法声明,如下所示:

<xacro:property name="props" value="${dict(a=1, b=2, c=3)}"/>
<xacro:property name="props_alt" value="${dict([('1a',1), ('2b',2), ('3c',3)])}"/>
<xacro:property name="numbers" value="${[1,2,3,4]}"/>

或者从 YAML 文件加载,如下所示:

<xacro:property name="yaml_file" value="$(find package)/config/props.yaml" />
<xacro:property name="props" value="${load_yaml(yaml_file)}"/>

从 YAML 文件加载的 xacro 属性被视为字典。 因此,如果props.yaml被加载到props xacro 属性中(如上所述)并且包含如下内容:

val1: 10
val2: 20

则可以使用如下方法读取:

<xacro:property name="val1" value="${props['val1']}" />

八、从 CMakeLists.txt 构建

以下代码片段展示了如何在包的 make 调用期间使用 xacro:

# Generate .world files from .world.xacro files
find_package(xacro REQUIRED)
# You can also add xacro to the list of catkin packages:
#   find_package(catkin REQUIRED COMPONENTS ... xacro)# Xacro files
file(GLOB xacro_files ${CMAKE_CURRENT_SOURCE_DIR}/worlds/*.world.xacro)foreach(it ${xacro_files})# remove .xacro extensionstring(REGEX MATCH "(.*)[.]xacro$" unused ${it})set(output_filename ${CMAKE_MATCH_1})# create a rule to generate ${output_filename} from {it}xacro_add_xacro_file(${it} ${output_filename})list(APPEND world_files ${output_filename})
endforeach(it)# add an abstract target to actually trigger the builds
add_custom_target(media_files ALL DEPENDS ${world_files})

虽然此 cmake 代码提供了对目标名称和构建顺序的完全控制,但也有一个便捷宏:

file(GLOB xacro_files worlds/*.world.xacro)
xacro_add_files(${xacro_files} TARGET media_files)

如果希望生成 .urdf 文件,可以提供以 .urdf.xacro 结尾的输入文件,CMake 函数将删除 .xacro 后缀。

九、处理顺序

通常的方法是,xacro 首先加载所有 <include> 的内容,然后处理所有属性和宏定义,最后实例化宏并计算表达式。因此,后面的属性或宏定义将覆盖前面的。此外,条件标签 <if><unless> 对宏或属性定义以及附加文件的 <include> 没有影响。

Jade 中的新功能

自 ROS Jade 以来,xacro 提供了命令行选项 --inorder,允许按读取顺序处理整个文档。因此,将使用最后读取的属性或宏。还允许一些不错的新功能:

  • 如果将 <include> 标签分别放在宏或条件标签内,则可以推迟或完全抑制文件的包含。
  • 可以通过属性或宏参数指定包含文件名。
  • 通过在全局范围内改变属性,如果在宏中使用这些属性,宏的实例化可以产生不同的结果。
  • 属性定义可以是有条件的。
  • 宏可以在内部定义属性而不影响外部的东西。

因为 --inorder 处理功能更加强大,在 Jade 之后的未来版本中,它成为了默认方式,所以应该检查 xacro 文件的兼容性。通常,两种处理方式会给出相同的结果。可以像这样检查:

rosrun xacro xacro file.xacro > /tmp/old.xml
rosrun xacro xacro --inorder file.xacro > /tmp/new.xml
diff /tmp/old.xml /tmp/new.xml

如果两个文件有任何差异,应该检查并调整 xacro 文件。一个常见原因是校准数据(作为属性)加载较晚,在这种情况下,只需将它们移到前面,即使用之前。为了方便搜索错误放置的属性定义,可以使用选项 --check-order 运行 xacro 。如果有任何有问题的属性,将在 stderr 上列出:

Document is incompatible to --inorder processing.
The following properties were redefined after usage:
foo redefined in issues.xacro

使用命令行选项 -vv-vvv 可以增加详细级别来记录所有属性的定义。

十、调试语法错误

要获得更详细的语法错误输出,可以运行以下命令,该命令将 xacro 转成 urdf 并检查语法错误,如果没有安装该命令,可以使用 sudo apt install liburdfdom-tools 安装

cd <path_to_xacro_file>
check_urdf <(xacro model.xacro)

xacro model.urdf.xacro > tmp.urdf && check_urdf tmp.urdf && rm tmp.urdf

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/845264.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

机器人动力学模型与MATLAB仿真

机器人刚体动力学由以下方程控制&#xff01;&#xff01;&#xff01; startup_rvc mdl_puma560 p560.dyn 提前计算出来这些“disturbance”&#xff0c;然后在控制环路中将它“抵消”&#xff08;有时候也叫前馈控制&#xff09; 求出所需要的力矩&#xff0c;其中M项代表克服…

世界500强是如何解决邮件大附件影响业务问题的

电子邮件已成为众多企业沟通和文件传输的重要工具。然而&#xff0c;邮件发送大附件时&#xff0c;企业往往会遇到一系列挑战。本文将探讨邮件发送大附件的优劣势&#xff0c;分析其对业务可能造成的问题&#xff0c;并介绍500强企业是如何解决这些问题的。 邮件发送大附件的优…

V90 PN总线伺服通过FB285速度控制实现正弦位置轨迹运动(解析法和数值法对比测试)

V90总线伺服相关内容请参考专栏系列文章,这里不在详述 1、V90伺服PN总线速度随动控制 V90伺服PN总线速度随动控制(手摇轮功能)_手摇轮可以接总线plc吗?-CSDN博客文章浏览阅读632次。V90PN总线控制相关内容,请参考下面文章链接:博途1200/1500PLC V90 PN通信控制 (FB284功能…

Facebook的算法揭秘:如何塑造我们的信息

在当今数字化时代&#xff0c;Facebook已经成为人们日常生活中不可或缺的一部分。其信息流算法不仅决定着我们在平台上看到的内容&#xff0c;还对我们的观点、行为和体验产生了深远的影响。本文将深入探讨Facebook的算法运作方式&#xff0c;以及它对我们信息获取和社交行为的…

Java集合【超详细】2 -- Map、可变参数、Collections类

文章目录 一、Map集合1.1 Map集合概述和特点【理解】1.2 Map集合的基本功能【应用】1.3 Map集合的获取功能【应用】1.4 Map集合的两种遍历方式 二、HashMap集合2.1 HashMap集合概述和特点【理解】2.2 HashMap的组成、构造函数2.3 put、查找方法2.4 HashMap集合应用案例【应用】…

【c++入门】函数重载,引用,内联函数,auto

函数重载 函数重载概念 什么是函数重载&#xff1f; 函数重载&#xff1a;是函数的一种特殊情况&#xff0c;C允许在同一作用域中声明几个功能类似的同名函数&#xff0c;这些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同&#xff0c;常用来处理实现功能类似数据类…

pytorch学习day3

一、模型创建&#xff08;Module&#xff09; 网络创建流程 ​ 上面的图表展示了使用PyTorch创建神经网络模型的主要步骤。每个步骤按顺序连接&#xff0c;展示了从导入必要的库到最终测试模型的整个流程&#xff1a; 导入必要的库&#xff1a;首先导入PyTorch及其相关模块。定…

【Tlias智能学习辅助系统】03 部门管理 前后端联调

Tlias智能学习辅助系统 03 部门管理 前后端联调 前端环境 前端环境 链接&#xff1a;https://pan.quark.cn/s/8720156ed6bf 提取码&#xff1a;aGeR 解压后放在一个不包含中文的文件夹下&#xff0c;双击 nginx.exe 启动服务 跨域的问题已经被nginx代理转发了&#xff0c;所以…

vs code 中使用SSH 连接远程的Ubuntu系统

如下图&#xff0c;找到对应的位置 在电脑上找到以下位置 打开配置如下&#xff0c;记住&#xff0c;那个root为你的用户名&#xff0c;这个用户名&#xff0c;具体根据你的用户名来设置&#xff0c;对应的密码就是你登录Ubuntu时的密码 Host root192.168.0.64User rootHostNa…

第N3周:Pytorch文本分类入门

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制&#x1f680; 文章来源&#xff1a;K同学的学习圈子 这里借用K同学的一张图片大致说明本次任务流程。 1.本次所用AG News数据集介绍 AG…

汽车IVI中控开发入门及进阶(二十三):i.MX8

前言: IVI市场的复杂性急剧增加,而TimeToMarket在几代产品中从5年减少到2-3年。Tier1正在接近开放系统的模型(用户可以安装应用程序),从专有/关闭源代码到标准接口/开放源代码,从软件堆栈对系统体系结构/应用层/系统验证和鉴定的完全所有权,越来越依赖第三方中间件和平…

优思学院|作为质量工程师,需要考哪些证书?别浪费你的气力,一张就够!

质量工程师做什么呢&#xff1f;他们的主要任务就是确保产品和服务的质量&#xff0c;以满足客户需求并超越竞争对手。尽管市场上有各种各样的质量管理认证&#xff0c;但优思学院认为&#xff0c;专注于六西格玛的学习和认证就足够了。 为什么选择六西格玛&#xff1f; 第一…

C++青少年简明教程:While和Do-while循环语句

C青少年简明教程&#xff1a;While和Do-while循环语句 C的while和do-while语句都是循环控制语句&#xff0c;用于重复执行一段代码。while语句在循环开始前检查循环条件&#xff0c;而do-while语句在循环结束后检查循环条件。 使用while循环时&#xff0c;如果需要在每次迭代前…

12V升20V3.5A升压恒压WT3207

12V升20V3.5A升压恒压WT3207 WT3207是一款高效PWM升压控制器&#xff0c;采用SO-8封装设计&#xff0c;专为低输入电压应用优化。该控制器支持5V至36V的宽输入电压范围&#xff0c;使其能够有效提升12V、15V和19V系统的电压水平&#xff0c;特别适合于两节或三节锂离子电池供电…

LabVIEW超声波局部放电检测系统开发

LabVIEW超声波局部放电检测系统开发 在高压电力系统中&#xff0c;局部放电(PD)是导致绝缘失效的主要原因之一。局部放电的检测对于确保电力系统的可靠运行至关重要。开发了一种基于LabVIEW软件的超声波局部放电检测系统的设计与实现。该系统利用数字信号处理技术&#xff0c;…

Python | Leetcode Python题解之第119题杨辉三角II

题目&#xff1a; 题解&#xff1a; class Solution:def getRow(self, rowIndex: int) -> List[int]:row [1, 1]if rowIndex < 1:return row[:rowIndex 1]elif rowIndex > 2:for i in range(rowIndex - 1):row [row[j] row[j 1] for j in range(i 1)]row.inser…

【Python入门学习笔记】Python3超详细的入门学习笔记,非常详细(适合小白入门学习)

Python3基础 想要获取pdf或markdown格式的笔记文件点击以下链接获取 Python入门学习笔记点击我获取 1&#xff0c;Python3 基础语法 1-1 编码 默认情况下&#xff0c;Python 3 源码文件以 UTF-8 编码&#xff0c;所有字符串都是 unicode 字符串。 当然你也可以为源码文件指…

【数据结构】二叉树运用及相关例题

文章目录 前言查第K层的节点个数判断该二叉树是否为完全二叉树例题一 - Leetcode - 226反转二叉树例题一 - Leetcode - 110平衡二叉树 前言 在笔者的前几篇篇博客中介绍了二叉树的基本概念及基本实现方法&#xff0c;有兴趣的朋友自己移步看看。 这篇文章主要介绍一下二叉树的…

iframe内嵌网页自适应缩放 以展示源网页的比例尺寸

需求:这是我最近开发的低代码平台遇到的需求 ,要求将配置好的应用在弹框中预览(将预览网页内嵌入弹框中) 但是内嵌进入后 他会截取一部分(我源网站网页尺寸 是1980x1080 或者 3060X2160等等) 但是我这个dialog弹框只有我自定义的1000多px的宽高 他只会展示我iframe网页的一部分…

Linux - 磁盘管理1

1.磁盘的分区 1.1 磁盘的类型&#xff08;标签&#xff09; MBR&#xff1a; ① 最大支持2T以内的硬盘 ② 有主分区p 拓展分区e 逻辑分区l之分 > 主分区编号1-4&#xff0c;主分区可以格式化使用 拓展分区编号1-4&#xff0c;拓展分区不能格式化 拓展分区最多能有1个&…