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

news2025/1/20 1:57:20

在这里插入图片描述

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 extension
  string(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.coloradmin.cn/o/1719637.html

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

相关文章

连锁超市能源能效管理方案

1.概述 连锁超市的能源消耗是其运营成本的重要组成部分。有效的能源能效管理不仅可以降低运营成本&#xff0c;也有助于环保&#xff0c;实现可持续发展。本文将探讨几种关键的能源能效管理策略。 2.智能照明系统 采用智能照明系统是提高能效的关键一步。这些系统可以根据店…

运维开发详解之指标收集

一、指标收集 运维开发中的指标收集是指收集、监控和分析系统运行的各种指标数据&#xff0c;用于评估系统的性能、健康状况和可靠性。这些指标可以包括服务器的 CPU 使用率、内存利用率、磁盘空间使用情况、网络流量等等。 指标收集的目的是为了及时发现系统存在的问题&…

【题解 | 分享】2023年十四届蓝桥杯国赛(Java B组)

互质 答案&#xff1a;640720414 参考&#xff1a; public class Main {static int mod 1000000007;public static void main(String[] args) {long sum power(2023, 2023);long p1 ((sum % mod) * power( 7, mod - 2)) % mod;long p2 ((sum % mod) * power( 17, mod -…

【Python爬虫--scrapy+selenium框架】超详细的Python爬虫scrapy+selenium框架学习笔记(保姆级别的,非常详细)

六&#xff0c;selenium 想要下载PDF或者md格式的笔记请点击以下链接获取 python爬虫学习笔记点击我获取 Scrapyselenium详细学习笔记点我获取 Python超详细的学习笔记共21万字点我获取 1&#xff0c;下载配置 ## 安装&#xff1a; pip install selenium## 它与其他库不同…

docker compose完成简单项目部署

1. 项目环境 centos7 docker mysql redis ruoyi项目 ruoyi项目链接&#xff1a;https://gitee.com/y_project/RuoYi-Vue.git 2. 进行项目前后端代码打包 后端打包&#xff1a; 修改mysql连接的相关配置文件 RuoYi-Vue/ruoyi-admin/src/main/resources/application-dru…

软件和系统集成项目确认测试报告的费用需要多少?

确认测试报告 软件和系统集成项目确认测试报告的费用因多种因素而异&#xff0c;包括项目的规模、复杂度、测试范围、测试周期等。第三方软件测试机构价格区间一般是几千到几万不等&#xff0c;还有些会根据建设费用的2-5%进行收费。 一般来说&#xff0c;软件和系统集成项目…

2024年5月架构试题

2024年5月份架构师考试真题完整版 截至2024-5-28 19:24:14已全部收录完成 共75道选择题&#xff0c;5道案例题&#xff0c;4道论文题。题目顺序不分先后。 全网最全的2024年5月份架构师考试真题回忆版&#xff0c;包含答案和解析。 选择题 计算机基础 操作系统调度算法 选先来先…

Linux基本命令的使用(cp mv)

一、cp命令-1 1、CP命令作用&#xff1a;复制一个源文件到目标文件&#xff08;夹&#xff09; 2、 语法&#xff1a;cp [选项] 源文件 目标文件&#xff08;夹&#xff09; ① 复制到文件夹下&#xff0c;则文件名保持不变 ② 复制到文件中&#xff0c;则文件名变更 二、cp命…

基于安卓的虫害识别软件设计--(1)模型训练与可视化

引言 简介&#xff1a;使用pytorch框架&#xff0c;从模型训练、模型部署完整地实现了一个基础的图像识别项目计算资源&#xff1a;使用的是Kaggle&#xff08;每周免费30h的GPU&#xff09; 1.创建名为“utils_1”的模块 模块中包含&#xff1a;训练和验证的加载器函数、训练…

Uniapp发布流程存档

发布成小程序 配置微信小程序的appid 配置小程序的域名 修改静态资源路径为线上路径 发布成H5 配置H5 发行 运行 发布成安卓 基础配置

JS-Lodash工具库

文档&#xff1a;Lodash Documentation orderBy函数&#xff1a;根据条件进行排序 注&#xff1a;第一个是要排序的数组&#xff0c;第二个是根据什么字段进行排序&#xff0c;第三个是排序的方式&#xff08;desc倒序&#xff09; 安装方式&#xff1a;Lodash npm i lodash…

Presto 从提交SQL到获取结果 源码详解(3)

物理执行计划 回到SqlQueryExecution.startExecution() &#xff0c;执行计划划分以后&#xff0c; // 初始化连接&#xff0c;获取Connect 元数据&#xff0c;添加会话&#xff0c;初始ConnectId metadata.beginQuery(getSession(), plan.getConnectors()); // 构建物理执行…

关于MD5

首先还是介绍一下关于md5的基本信息&#xff1a; MD5&#xff08;Message Digest Algorithm 5&#xff09;是一种常用的哈希函数&#xff0c;用于产生128位&#xff08;16字节&#xff09;的哈希值&#xff0c;通常以32个十六进制数字表示。MD5广泛用于计算文件或文本数据的校…

LeetCode-131 分割回文串

LeetCode-131 分割回文串 题目描述解题思路C 代码 题目描述 给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使每个子串都是 回文串。返回 s 所有可能的分割方案。 示例 1&#xff1a; 输入&#xff1a;s “aab” 输出&#xff1a;[[“a”,“a”,“b”],…

Zynq学习笔记--AXI4-Stream 图像数据从仿真输出到图像文件

目录 1. 简介 2. 构建工程 2.1 Vivado 工程 2.2 TestBench 代码 2.3 关键代码分析 3. VPG Background Pattern ID (0x0020) Register 4. 总结 1. 简介 使用 SystemVerilog 将 AXI4-Stream 图像数据从仿真输出到图像文件 (PPM)。 用到的函数包括 $fopen、$fwrite 和 $f…

vmware esxi虚拟化数据迁移

1、启用esxi的ssh 登录esxi的web界面&#xff0c;选择主机-》操作——》服务——》启动ssh 2.xshell登录esxi 3、找到虚拟机所在目录 blog.csdnimg.cn/direct/d57372536a4145f2bcc1189d02cc7da8.png)#### 3在传输数据前需关闭防火墙服务 查看防火墙状态&#xff1a;esxcli …

Android MediaCodec 简明教程(九):使用 MediaCodec 解码到纹理,使用 OpenGL ES 进行处理,并编码为 MP4 文件

系列文章目录 Android MediaCodec 简明教程&#xff08;一&#xff09;&#xff1a;使用 MediaCodecList 查询 Codec 信息&#xff0c;并创建 MediaCodec 编解码器Android MediaCodec 简明教程&#xff08;二&#xff09;&#xff1a;使用 MediaCodecInfo.CodecCapabilities 查…

【传知代码】双深度学习模型实现结直肠癌检测(论文复现)

前言&#xff1a;在医学领域&#xff0c;科技的进步一直是改变人类生活的关键驱动力之一。随着深度学习技术的不断发展&#xff0c;其在医学影像诊断领域的应用正日益受到关注。结直肠癌是一种常见但危害极大的恶性肿瘤&#xff0c;在早期发现和及时治疗方面具有重要意义。然而…

【VSCode】快捷方式log去掉分号

文章目录 一、引入二、解决办法 一、引入 我们使用 log 快速生成的 console.log() 都是带分号的 但是我们的编程习惯都是不带分号&#xff0c;每次自动生成后还需要手动删掉分号&#xff0c;太麻烦了&#xff01; 那有没有办法能够生成的时候就不带分号呢&#xff1f;自然是有…

C++ 特殊运算符

一 赋值运算符 二 等号作用 三 优先级和结合顺序 四 左值和右值 五 字节数运算符 条件运算符 使用条件运算符注意 逗号运算符 优先级和结合顺序 总结