1

1 前言

本案例摘录自胡春旭老师的《ROS机器人开发实践》
本文规定星号代表需要用户自定义

2 解读文件

2.1 定义标头

<?xml version="1.0"?>
<robot name="****" xmlns:xacro="http://www.ros.org/wiki/xacro">
...
</robot>

2.2 定义杆件外观颜色

<!-- Defining the colors used in this robot -->
<material name="Black">
    <color rgba="0 0 0 1"/>
</material>

2.3 定义参数(相当于程序里的变量)

<xacro:property name="****" value="****" />

2.4 定义宏(相当于程序里的函数)

    <!-- Macro for inertia matrix -->
    <xacro:macro name="****" params="**** **** ...">
    ...
    </xacro:macro>

其中macro中的name相当于规定函数名,param即为形参名。
在macro中引用param的方式:${形参名};并且支持四则运算。如下所示:

    <xacro:macro name="sphere_inertial_matrix" params="m r">
        <inertial>
            <mass value="${m}" />
            <inertia ixx="${2*m*r*r/5}" ixy="0" ixz="0"
                iyy="${2*m*r*r/5}" iyz="0" 
                izz="${2*m*r*r/5}" />
        </inertial>
    </xacro:macro>

调用自身文件内macro的方式:

<macro名  macro.param=**** />

调用外部文件的macro的方式:

<xacro:include filename="$(find 包名)/urdf/xacro名.xacro" />
<macro名  macro.param=****/>

3 示例xacro文件

具体小车模型如下所示:
小车模型.jpg
示例文件名robot_body.xacro

<?xml version="1.0"?>
<robot name="robot_body" xmlns:xacro="http://www.ros.org/wiki/xacro">

    <!-- Defining the colors used in this robot -->
    <material name="Black">
        <color rgba="0 0 0 1"/>
    </material>
    
    <material name="White">
        <color rgba="1 1 1 1"/>
    </material>

    <material name="Blue">
        <color rgba="0 0 1 1"/>
    </material>
    
    <!-- PROPERTY LIST -->
    <!--All units in m-kg-s-radians unit system -->
    <xacro:property name="M_PI" value="3.14" />

    <!-- Main body length, width, height and mass -->
    <xacro:property name="base_mass"        value="0.5" /> 
    <xacro:property name="base_link_radius" value="0.13"/>
    <xacro:property name="base_link_length" value="0.005"/>

    <xacro:property name="motor_x" value="-0.05"/>

    <!-- Caster radius and mass -->
    <xacro:property name="caster_radius"          value="0.016" /> 
    <xacro:property name="caster_mass"            value="0.01" /> 
    <xacro:property name="caster_joint_origin_x"  value="-0.12" />

    <!-- Wheel radius, height and mass -->
    <xacro:property name="wheel_radius" value="0.033" /> 
    <xacro:property name="wheel_height" value="0.017" />
    <xacro:property name="wheel_mass"   value="0.1" />

    <!-- Macro for inertia matrix -->
    <xacro:macro name="sphere_inertial_matrix" params="m r">
        <inertial>
            <mass value="${m}" />
            <inertia ixx="${2*m*r*r/5}" ixy="0" ixz="0"
                iyy="${2*m*r*r/5}" iyz="0" 
                izz="${2*m*r*r/5}" />
        </inertial>
    </xacro:macro>

    <xacro:macro name="cylinder_inertial_matrix" params="m r h">
        <inertial>
            <mass value="${m}" />
            <inertia ixx="${m*(3*r*r+h*h)/12}" ixy = "0" ixz = "0"
                iyy="${m*(3*r*r+h*h)/12}" iyz = "0"
                izz="${m*r*r/2}" /> 
        </inertial>
    </xacro:macro>

    <!-- Macro for wheel joint -->
    <xacro:macro name="wheel" params="lr translateY">
        <!-- lr: left, right -->
        <link name="wheel_${lr}_link">
            <visual>
                <origin xyz="0 0 0" rpy="${M_PI/2} 0  0 " /> 
                <geometry>
                    <cylinder length="${wheel_height}" radius="${wheel_radius}" />
                </geometry>
                <material name="Black" />
            </visual>
            <collision>
                <origin xyz="0 0 0" rpy="${M_PI/2} 0 0 " />
                <geometry>
                    <cylinder length="${wheel_height}" radius="${wheel_radius}" />
                </geometry>
            </collision>
            <cylinder_inertial_matrix  m="${wheel_mass}" r="${wheel_radius}" h="${wheel_height}" />
        </link>

        <joint name="base_to_wheel_${lr}_joint" type="continuous">
            <parent link="base_link"/>
            <child link="wheel_${lr}_link"/>
            <origin xyz="${motor_x} ${translateY * base_link_radius} 0" rpy="0 0 0" /> 
            <axis xyz="0 1 0" rpy="0  0" />
        </joint>
    </xacro:macro>

    <!-- Macro for caster joint -->
    <xacro:macro name="caster" params="fb translateX">
        <!-- fb: front, back -->
        <link name="${fb}_caster_link">
            <visual>
                <origin xyz="0 0 0 " rpy="0 0 0" /> 
                <geometry>
                    <sphere radius="${caster_radius}" />
                </geometry>
                <material name="White" />
            </visual>  
            <collision>
                <geometry>
                    <sphere radius="${caster_radius}" />
                </geometry>
                <origin xyz="0 0 0 " rpy="0 0 0" /> 
            </collision>      
            <sphere_inertial_matrix  m="${caster_mass}" r="${caster_radius}" />
        </link>

        <joint name="base_to_${fb}_caster_joint" type="fixed">
            <parent link="base_link"/>
            <child link="${fb}_caster_link"/>
            <origin xyz="${translateX*caster_joint_origin_x} 0 ${-caster_radius}" rpy="0 0 0"/>
        </joint>
    </xacro:macro>

    <!-- BASE-FOOTPRINT -->
    <!-- base_footprint is a fictitious link(frame) that is on the ground right below base_link origin -->
    <xacro:macro name="robot_body">
        <link name="base_footprint">
            <visual>
                <origin xyz="0 0 0" rpy="0 0 0" />
                <geometry>
                    <box size="0.001 0.001 0.001" />
                </geometry>
            </visual>
        </link>

        <joint name="base_footprint_joint" type="fixed">
            <origin xyz="0 0 ${wheel_radius}" rpy="0 0 0" />
            <parent link="base_footprint"/>
            <child link="base_link" />
        </joint>

        <!-- BASE-LINK -->
        <!--Actual body/chassis of the robot-->
        <link name="base_link">
            <cylinder_inertial_matrix  m="${base_mass}" r="${base_link_radius}" h="${base_link_length}" />
            <visual>
                <origin xyz=" 0 0 0" rpy="0 0 0" />
                <geometry>
                    <cylinder length="${base_link_length}" radius="${base_link_radius}"/>
                </geometry>
                <material name="Blue" />
            </visual>

            <collision>
                <origin xyz="0 0 0" rpy="0 0 0" />
                <geometry>
                    <cylinder length="${base_link_length}" radius="${base_link_radius}"/>
                </geometry>
            </collision>   
        </link>

        <!-- Wheel Definitions -->
        <wheel lr="right"  translateY="1" />
        <wheel lr="left"  translateY="-1" />

        <!-- Casters Definitions -->
        <caster fb="front"  translateX="-1" />

    </xacro:macro>
</robot>

4.调用机器人模型

建立总xacro文件,以调用宏(即macro)robot_body(处于robot_body.xacro文件),总文件名为robot.xacro

<?xml version="1.0"?>
<robot name="robot" xmlns:xacro="http://www.ros.org/wiki/xacro">

    <xacro:include filename="$(find 包名)/urdf/robot_body.xacro" />
    <robot_body />

</robot>

在ROS中,xacro文件要转化urdf文件来调用,命令如下:

rosrun xacro xacro --inorder xacro名.xacro > ****.urdf

一般我们可以将该命令写入launch文件。因此launch文件,可以写成如下所示:

<?xml version = "1.0"?>
<launch>
    <arg name = "model" default = "$(find xacro)/xacro --inorder '$(find pkg名)/urdf/robot.xacro'" />
    <arg name = "gui" default = "true" />
    <param name = "robot_description" command = "$(arg model)" />
    <param name = "use_gui" value = "$(arg gui)" />
    <node name = "joint_state_publisher" pkg = "joint_state_publisher" type = "joint_state_publisher" />
    <node name = "robot_state_publisher" pkg = "robot_state_publisher" type = "state_publisher" />
    <node name = "rviz" pkg = "rviz" type = "rviz" args = "-d $(find urdf_tutorial)/urdf.rviz" />
</launch>

以上纯属个人见解~


我不是尾田
1 声望3 粉丝