xacro优化urdf代码编写

“🎆🎆🎆这是一场盛大的开始!🎆🎆🎆”
本文章是基于赵虚左老师的ROS教程的学习总结,属于作者的学习笔记。如有错误不足,请不吝指点,十分感谢!😊😊😊

xacro介绍

概念
Xacro 是 XML Macros 的缩写,Xacro 是一种 XML 宏语言,是可编程的 XML。

原理
Xacro 可以声明变量,可以通过数学运算求解,使用流程控制控制执行顺序,还可以通过类似函数的实现,封装固定的逻辑,将逻辑中需要的可变的数据以参数的方式暴露出去,从而提高代码复用率以及程序的安全性。

作用
较之于纯粹的 URDF 实现,可以编写更安全、精简、易读性更强的机器人模型文件,且可以提高编写效率。

语法详解

xacro 提供了可编程接口,类似于计算机语言,包括变量声明调用、函数声明与调用等语法实现。在使用 xacro 生成 urdf 时,根标签robot中必须包含命名空间声明:xmlns:xacro="http://wiki.ros.org/xacro"

1.属性与算数运算 用于封装 URDF 中的一些字段,比如: PAI 值,小车的尺寸,轮子半径 …

属性定义

<xacro:property name="xxxx" value="yyyy" />
属性调用

${属性名称}
算数运算

${数学表达式}
2.宏 类似于函数实现,提高代码复用率,优化代码结构,提高安全性

宏定义

<xacro:macro name="宏名称" params="参数列表(多参数之间使用空格分隔)">

.....

参数调用格式: ${参数名}

</xacro:macro>
宏调用

<xacro:宏名称 参数1=xxx 参数2=xxx/>
3.文件包含 机器人由多部件组成,不同部件可能封装为单独的 xacro 文件,最后再将不同的文件集成,组合为完整机器人,可以使用文件包含实现

文件包含

<robot name="xxx" xmlns:xacro="http://wiki.ros.org/xacro">
     <xacro:include filename="my_base.xacro" />
     <xacro:include filename="my_camera.xacro" />
     <xacro:include filename="my_laser.xacro" />
     .... 
</robot>
     

具体实现

部署流程:(最好是利用include标签的功能用不同的组成模块来组合为总体机器人文件)

  1. 分别编写不同组成模块的代码。(将需要的模型拆解构利用模块化思想)(其中需要注意的是其实每一个模块的robot标签的name是可以不同的,关键的是launch文件中的param name是独特的。后面会利用到。 )

  2. 编写launch文件集成rviz查看效果(注意转换坐标系 )。

  • base_link

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

    <xacro:property name="footprint_radius" value="0.001" />
    <!--  base_footprint -->
    <link name="base_footprint">
        <visual>
            <geometry>
                <sphere radius="${footprint_radius}"  />
            </geometry>
        </visual>
    </link>

    <xacro:property name="base_radius" value="0.1" />
    <xacro:property name="base_length" value="0.08" />
    <xacro:property name="lidi_hight" value="0.015" />
    <xacro:property name="base_joint_z" value="${base_length/2+lidi_hight}" />
    <!--  base_link -->
    <link name="base_link" >
        <visual>
            <geometry>
                <cylinder radius="0.1" length="0.08" />

            </geometry>

            <origin xyz="0 0 0 " rpy="0 0 0" />

            <material name="base_color">
                <color rgba="0 0.5 0.8 0.8" />
            </material>
        </visual>
    </link>

    <joint name="link2footprint" type="fixed">
        <parent link="base_footprint"  />
        <child link="base_link"  />
        <!--  -->
        <origin xyz="0 0 0.055" rpy="0 0 0" />
    </joint>

    <!-- 3. wheel -->

    <xacro:property name="wheel_radius" value="0.0325" />
    <xacro:property name="wheel_length" value="0.015" />
    <xacro:property name="PI" value="3.1415927" />
    <xacro:property name="wheel_joint_z" value="${(base_length / 2 +lidi_hight - wheel_radius) * -1}" />

    <!-- 
        wheel_name:left or right
        flag: 1 or -1
     -->
    <xacro:macro name="wheel_func" params="wheel_name flag">
    <!-- link  &  joint -->
     <link name="${wheel_name}_wheel">
        <visual>
            <geometry>
                <cylinder radius="${wheel_radius}" length="${wheel_length}" />
            </geometry>
            <origin xyz="0 0 0" rpy="${PI / 2} 0 0" />
            <material name="black">
                <color rgba="0.0 0.0 0.0 0.9" />
            </material>
        </visual>

    </link>

    <!-- 
        joint
     -->
    <joint name="${wheel_name}_wheel2base_link" type="continuous">
        <parent link="base_link" />
        <child link="${wheel_name}_wheel" />
        <origin xyz="0 ${0.1 * flag} ${wheel_joint_z}" />
        <axis xyz="0 1 0" />
    </joint>

    </xacro:macro>

    <xacro:wheel_func wheel_name="left" flag="1"  />
    <xacro:wheel_func wheel_name="right" flag="-1"  />

    <!-- 4.universal_wheel -->

    <xacro:property name="small_wheel_radius" value="0.0075" />
    <xacro:property name="small_joint_z" value="${(base_length / 2 +lidi_hight - small_wheel_radius) * -1}" />

    <xacro:macro name="universal_wheel_func" params="universal_wheel_name flag">
    <link name="${universal_wheel_name}_wheel">
        <visual>
            <geometry>
                <sphere radius="${small_wheel_radius}"   />

            </geometry>

            <origin xyz="0 0 0" rpy="0 0 0"  />

            <material name="universal_wheel_color">
                <color rgba="0 0 0 0.8"  />
            </material>
        </visual>
    </link>

    <joint name ="${universal_wheel_name}2_link" type="continuous">
        <parent link="base_link"  />
        <child link="${universal_wheel_name}_wheel"  />

        <origin xyz="${0.08 * flag} 0 ${small_joint_z}" rpy="0 0 0"  />
        <axis xyz="0 1 0" />
    </joint>
    </xacro:macro>

    <xacro:universal_wheel_func universal_wheel_name="front" flag="1"   />
    <xacro:universal_wheel_func universal_wheel_name="back" flag="-1"  />
</robot>
  • camera

<robot name="mycar" xmlns:xacro="http://www.ros.org/wiki/xacro">
    <!-- camera -->
    <!-- 1.paramter -->
    <!-- 
        link: height  width  length

        joint: x y z
     -->

     <xacro:property name="camera_length" value="0.02" /> 
     <xacro:property name="camera_width" value="0.05" />
     <xacro:property name="camera_height" value="0.05" />
     <xacro:property name="joint_camera_x" value="0.08" />
     <xacro:property name="joint_camera_y" value="0" />
     <xacro:property name="joint_camera_z" value="${base_length / 2+camera_height / 2}" />

    <!-- 2.link -->
    <link name="camera">
        <visual>

            <geometry>
                <box size="${camera_length} ${camera_width} ${camera_height}"  />
            </geometry>

            <material name="black">
                <color rgba=" 0 0 0 1" />
            </material>
        </visual>

    </link>

    <!-- 3.joint -->
    <joint name="camera2base" type="fixed">
        <parent link="base_link" />
        <child link="camera"  />

        <origin xyz="${joint_camera_x} ${joint_camera_y} ${joint_camera_z}"  rpy="0 0 0" />
    </joint>
    
</robot>

  • laser

<robot name="mycar" xmlns:xacro="http://www.ros.org/wiki/xacro">
    <!-- laser -->
    <!-- paramter -->
    <!-- 
        1.support:
        radius:0.01   length:0.15

        2.laser
        radius:0.03  length:0.05
        x y z
     -->

    <!-- 1.support -->
    <!-- 1.1 link -->
    <xacro:property name="support_radius" value="0.01" />
    <xacro:property name="support_length" value="0.15" />
    
    <link name="support">
        <visual>
            <geometry>
                <cylinder radius="${support_radius}" length="${support_length}"  />
            </geometry>

            <material name="red">
                <color rgba="1 0 0 0.6" />
            </material>
        </visual>
    </link>

    <!-- 1.2 joint -->
    <joint name="support2base" type="fixed">
        <parent link="base_link" />
        <child link="support" />

        <origin xyz="0 0 ${base_length / 2 + support_length / 2}" rpy="0 0 0 " />

    </joint>

    <!-- 2.laser --> 
    <!-- 2.1 link -->
    <xacro:property name="laser_radius" value="0.03" /> 
    <xacro:property name="laser_length" value="0.05" />
    <link name="laser">
        <visual>
            <geometry>
                <cylinder radius="${laser_radius}" length="${laser_length}" />
            </geometry>

            <material name="black">
                <color rgba="0 0 0 0.6" />
            </material>
        </visual>
    </link>

    <!-- 2.2 joint-->
    <joint name="laser2support" type="fixed">
        <parent link="support"  />
        <child link="laser"  />

        <origin xyz="0 0 ${support_length / 2 + laser_length / 2}"  rpy="0 0 0" />
    </joint>

</robot>
  • car(集成文件)

<robot name="mycar" xmlns:xacro="http://www.ros.org/wiki/xacro">
    <!-- include base camera laser  xacro file -->
    <xacro:include filename="demo05_car_base.xacro" />
    <xacro:include filename="demo06_car_camera.xacro" />
    <xacro:include filename="demo07_car_laser.xacro" />

    
</robot>
  • launch(集成)

<launch>
    <!--1.在参数服务器中载入urdf文件-->
    <!--textfile : 直接指向urdf 将整个urdf转入到参数服务器中-->
    <param name="robot_description" command="$(find xacro)/xacro '$(find urdf01_rviz)/urdf/xacro/car.xacro'" />
    <!-- 2.启动 rviz -->
    <node pkg="rviz" type="rviz" name="rviz"  args="-d $(find urdf01_rviz)/config/show_mycar.rviz"/>
    <!-- 机器人以及关节发布节点   需要着重注意 -->
    <node pkg="joint_state_publisher" type="joint_state_publisher" name="joint_state_publisher" />

    <node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" />
    <!-- 添加控制关节运动节点 -->
    <!-- <node pkg="joint_state_publisher_gui" type="joint_state_publisher_gui" name="joint_state_publisher_gui" /> -->
</launch>

在这里插入图片描述

仿真部署过程中的错误解决

检查方案

在编写xacro文件时,难免出现错误,但是对于xml文件来说它不会直接告诉你那里是有错误的或者是错在哪里,这个这个标签化编程语言的一些局限。
为了在完成一个阶段后来检查错误。我们可以使用ros中的xacrourdf功能包来排查错误:

1. 保存编写好的xacro文件后,在xacro目录下打开终端,并输入rosrun xacro xacro (需要检查的文件).xacro
查看是否转为urdf文件,如果转化错误的话,在期间可以检查错误内容和大致位置。
在这里插入图片描述

如果转化成功的话便会有如下显示(文件没有语法错误):

在这里插入图片描述

2. 或者使用ros自带的工具实现语法检查。(前提是将xacro文件转为urdf文件—>先将 xacro 文件解析成 urdf 文件:rosrun xacro xacro xxx.xacro > xxx.urdf
check_urdf语法检查
进入urdf文件所属目录,调用:check_urdf urdf文件,如果不抛出异常,说明文件合法,否则非法。

在这里插入图片描述

错误解决

  • 类似这种错误一般都是代码中包含中文注释的问题

在这里插入图片描述

  • launch文件报错:
    具体可以为如下几种情况:
    1.xml文件转义格式错误 即$(find xacro)/xacro 后面的功能包路径需要用' '括起来。
    2.文件路径错误,需要再仔细检查。
    3.xacro文件的命名有问题:将文件后缀名更改:从.urdf.xacro—>.xacro 运行成功。

在这里插入图片描述

launch文件报错解决方法在这里插入图片描述最终解决办法可以参考此blog

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值