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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C#中接口的显式实现与隐式实现及其相关应用案例

C#中接口的显式实现与隐式实现 最近在学习演化一款游戏项目框架时候&#xff0c;框架作者巧妙使用接口中方法的显式实现来变相对接口中方法进行“密封”&#xff0c;增加实现接口的类访问方法的“成本”。 接口的显式实现和隐式实现&#xff1a; 先定义一个接口&#xff0c;接口…

KotlinConf 2024:深入了解Kotlin Multiplatform (KMP)

KotlinConf 2024&#xff1a;深入了解Kotlin Multiplatform (KMP) 在近期的Google I/O大会上&#xff0c;我们推荐了Kotlin Multiplatform (KMP)用于跨移动、网页、服务器和桌面平台共享业务逻辑&#xff0c;并在Google Workspace中采用了KMP。紧接着&#xff0c;KotlinConf 2…

豆包浏览器插件会造成code标签内容无法正常显示

启用状态&#xff1a;页面的代码会显示不正常 禁用后&#xff0c;正常显示 害得我重置浏览器设置&#xff0c;一个个测试

CentOS7.9部署安装OpenGauss 5.0.2企业版

1、更新系统: yum update -y 2、更改主机名&#xff1a; hostnamectl set-hostname opendb01 3、关闭透明页&#xff1a; echo never > /sys/kernel/mm/transparent_hugepage/enabled echo never > /sys/kernel/mm/transparent_hugepage/defrag# 加入开机自启动 echo …

微信小程序使用echarts

思路 五个tab公用一个柱状图组件切换tab以及切换时间改变数据&#xff0c;传入子组件&#xff0c;子组件监听数据重新更新点击柱状图显示具体数值每个时间点有两个柱子&#xff08;高压和低压&#xff09;&#xff0c;柱状图显示高压的最大值到最小值的范围除了血压其余只有一…

【Epoch,Batch,Iteration】深度学习模型训练相关基础概念光速理解!

&#x1f525;模型训练相关基础概念&#xff01; Epoch: 一次 epoch 代表整个训练数据集已经被完整地送入神经网络进行了一轮训练。通常&#xff0c;模型需要多次 epoch 才能充分学习数据集中的模式。Batch: 由于数据集可能过大&#xff0c;无法一次性全部加载到内存中进行训练…

【前端】Mac安装node14教程

在macOS上安装Node.js版本14.x的步骤如下&#xff1a; 打开终端。 使用Node Version Manager (nvm)安装Node.js。如果你还没有安装nvm&#xff0c;可以使用以下命令安装&#xff1a; curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash 然后关…

LAMP分布式安全方案搭建网页 (LinuxCentOS7+Apache+Mariadb+PHP)包括服务端口及防火墙规则配置

目录 一、实验目的 二、设计方案及规划 三、实验内容及步骤 &#xff08;1&#xff09;实验前基础配置 &#xff08;2&#xff09;Test配置&#xff0c;安装Firefox浏览器和图形界面 &#xff08;3&#xff09;Web安装Apache &#xff08;4&#xff09;Database安装Mari…

2.4 Docker部署JDK

2.4 Docker部署JDK jdk17部署&#xff08;自定义镜像&#xff09; 1.在官网上下载jdk-17_linux-x64_bin.tar.gz&#xff0c;并安装到/usr/local目录下 cd /usr/local2.创建Dockerfile vim Dockerfile# 基于官方的Ubuntu 20.04镜像作为基础镜像 FROM ubuntu:20.04# 设置环境…

瑞吉外卖项目学习笔记(二)后台系统的员工管理业务开发

一、完善登录功能 1.1 问题分析 1.2 代码实现 package com.itheima.reggie.filter;//这是一个过滤器类 //登录检查过滤器import com.alibaba.fastjson.JSON; import com.itheima.reggie.common.R; import lombok.extern.slf4j.Slf4j; import org.slf4j.Logger; import org.slf…

探索k8s集群的存储卷 emptyDir hostPath nfs

目录 一 含义 查看支持的存储卷类型 emptyDir存储卷 1.1 特点 1.2 用途 1.3部署 二、hostPath存储卷 一 含义 容器磁盘上的文件的生命周期是短暂的&#xff0c;这就使得在容器中运行重要应用时会出现一些问题。首先&#xff0c;当容器崩溃时&#xff0c;kubelet 会重…

磁盘配额的具体操作

磁盘配额&#xff1a; linux的磁盘空间有两个方面&#xff1a;第一个是物理空间&#xff0c;也就是磁盘的容量 第二个inode号耗尽&#xff0c;也无法写入 linux根分区&#xff1a;根分区的空间完全耗尽&#xff0c;服务程序崩溃&#xff0c;系统也无法启动了。 为了防止有人…

师彼长技以助己(2)产品思维

师彼长技以助己&#xff08;2&#xff09;产品思维 前言 我把产品思维称之为&#xff1a;人生底层的能力以及蹉跎别人还蹉跎自己的能力&#xff0c;前者说明你应该具备良好产品思维原因&#xff0c;后者是你没有好的产品思维去做产品带来的灾难。 人欲即天理 请大家谈谈看到这…

错误 0x80070570:文件或目录损坏且无法读取/无法访问[拒绝访问]-解决方法

1.起因&#xff1a;在挪动&#xff35;盘文件时&#xff0c;出现无法移动的报错提示&#xff1a; and无法访问[拒绝访问]: 2.原因&#xff3b;大多是胡乱拔出&#xff35;盘&#xff3d; &#xff3b;来自0x80070570 文件或目录损坏且无法读取 CHKDSK 修复方法-CSDN博客&#…

【介绍下SCSS的基本使用】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

【AI应用开发框架】应用phidata快速构建你的智能体(如个人知识库、自动选股等)

1.phidata是什么&#xff1f; AI APP开发框架&#xff0c;基于此框架可快速搭建智能体或智能助手以实现记忆、知识库及工具使用等功能。 2.框架是怎样的&#xff1f; 3.为什么选择phidata&#xff1f; 问题&#xff1a;LLMs 的上下文有限&#xff0c;无法执行具体动作 解决…

[数据集][目标检测]猫狗检测数据集VOC+YOLO格式8291张2类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;8291 标注数量(xml文件个数)&#xff1a;8291 标注数量(txt文件个数)&#xff1a;8291 标注…

LeetCode-131 分割回文串

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

1.8k Star!RAGApp:在任何企业中使用 Agentic RAG 的最简单方法!

原文链接&#xff1a;&#xff08;更好排版、视频播放、社群交流、最新AI开源项目、AI工具分享都在这个公众号&#xff01;&#xff09; 1.8k Star&#xff01;RAGApp&#xff1a;在任何企业中使用 Agentic RAG 的最简单方法&#xff01; &#x1f31f;在任何企业中使用 Agent…

大数据信用报告分析和评估有什么意义

大数据信用这个词在现在已经是很常见的了&#xff0c;只要是申贷的朋友对它就不陌生&#xff0c;在明面上的信用资质刚刚满足审核要求&#xff0c;但又要把控风险的时候&#xff0c;这个时候大数据信用就会作为风控机构交叉核查的重要依据。那你知道大数据信用报告分析和评估有…