ROS course 68: using xarco part 1

5 minute read

1. Environment

This post is tested under the following Environment:

Item Value
CPU AMD Ryzen 5 2600
Ubuntu 18.04
ROS Melodic

For installation, see 02 Install. The source code of all parts is upload of github, see 11 git for more detail.

2. Summary

URDF (Unified Robot Description Format) is the standard ROS XML representation of the robot model source. which result in very long file and hard to co-operate between team.

Let’s compare between urdf and xacro in industrial example. Baxter robot’s urdf is at baxer.urdf is 1600 lines long. By using xacro, the baxer.urdf is separated into 5 separated files which only 523 lines in summary. (xacro files is 1 , 2, 3, 4, 5 correspondingly)

Xacro have the following features. (See ros_wiki/xacro for full list and explaination)

  1. Property and property blocks : use to create and set variable
  2. Mathemetics
  3. Conditions
  4. Macros : very useful when statements are repeated or reused with modification defined by parameters
  5. Can use rospack
  6. Can include other xacro files

Source code is as follow

ros_lecture/vis_lecture/
├── launch
├── package.xml
├── rviz
├── src
├── stl
├── urdf
└── xacro
    ├── basic1.urdf
    ├── basic1.xacro
    ├── basic2.xacro
    ├── basic3.xacro  
    ├── basic4.xacro
    ├── basic5_h.xacro
    ├── basic5.xacro
    └── basic6.xacro

3. Example

3.1. property block

<!-- vis_lecture/xacro/basic1.xacro -->
<robot name="test_robot" xmlns:xacro="http://ros.org/wiki/xacro">

  <!-- Create property block -->
  <xacro:property name="side" value="0.5" />

  <link name="base_link">
    <visual>
      <origin rpy="0 0 0" xyz="0 0 0"/>
      <geometry>
        <!-- Use property block instead of fixed variable -->
        <box size="${side} ${side} ${side}" />
      </geometry>
      <material name="red">
        <color rgba="1.0 0.0 0.0 2.0"/>
      </material>
    </visual>
  </link>
</robot>

Run

roscd vis_lecture/xacro/
roslaunch urdf_tutorial display.launch model:=basic1.xacro

A box with size = 0.5 is created as follow

vis_xacro1.png

Unlike urdf, there isn’t check_xacro command to check whether xacro file is correctly written. So we need to convert xacro into urdf first, then use check_urdf tool to check genarated urdf. Use the following command to convert xacro into urdf

roscd vis_lecture/xacro/
rosrun xacro xacro basic1.xacro --inorder >basic1.urdf

Check detail of genarated urdf

<?xml version="1.0" ?>
<!-- =================================================================================== -->
<!-- |    This document was autogenerated by xacro from basic1.xacro                   | -->
<!-- |    EDITING THIS FILE BY HAND IS NOT RECOMMENDED                                 | -->
<!-- =================================================================================== -->
<robot name="test_robot" xmlns:xacro="http://ros.org/wiki/xacro">
  <link name="base_link">
    <visual>
      <origin rpy="0 0 0" xyz="0 0 0"/>
      <geometry>
        <box size="0.5 0.5 0.5"/>
      </geometry>
      <material name="red">
        <color rgba="1.0 0.0 0.0 2.0"/>
      </material>
    </visual>
  </link>
</robot>

Run the following command to check urdf.

roscd vis_lecture/xacro/
rosrun xacro xacro basic1.xacro --inorder >basic1.urdf
check_urdf basic1.urdf 

If there isn’t any error:

robot name is: test_robot
---------- Successfully Parsed XML ---------------
root Link: base_link has 0 child(ren)

3.2. Mathemetics

Xacro employs python to evaluate expressions enclosed in dollared-braces, ${}

<!-- vis_lecture/xacro/basic2.xacro -->
<robot name="test_robot" xmlns:xacro="http://ros.org/wiki/xacro">
  <xacro:property name="side" value="0.5" />
  <material name="red">
    <color rgba="1.0 0.0 0.0 2.0"/>
  </material>

  <link name="base_link"/>

  <joint name="body0_joint" type="fixed">
    <!-- Equation 1 -->
    <origin rpy="0 0 0" xyz="${0.5*cos(radians(0))} ${0.5*sin(radians(0))} 0"/>
    <parent link="base_link"/>
    <child  link="body0_link"/>
  </joint>
  <link name="body0_link">
    <visual>
      <geometry>
        <box size="0.1 0.1 0.1" />
      </geometry>
      <material name="red"/>
    </visual>
  </link>

  <joint name="body1_joint" type="fixed">
    <!-- Equation 2 -->
    <origin rpy="0 0 0" xyz="${0.5*cos(radians(30))} ${0.5*sin(radians(30))} 0"/>
    <parent link="base_link"/>
    <child  link="body1_link"/>
  </joint>
  <link name="body1_link">
    <visual>
      <geometry>
        <box size="0.1 0.1 0.1" />
      </geometry>
      <material name="red"/>
    </visual>
  </link>

  <joint name="body2_joint" type="fixed">
    <!-- Equation 3 -->
    <origin rpy="0 0 0" xyz="${0.5*cos(radians(60))} ${0.5*sin(radians(60))} 0"/>
    <parent link="base_link"/>
    <child  link="body2_link"/>
  </joint>
  <link name="body2_link">
    <visual>
      <geometry>
        <box size="0.1 0.1 0.1" />
      </geometry>
      <material name="red"/>
    </visual>
  </link>
</robot>

Run program

# install dependency if needed
# sudo apt install ros-melodic-urdf-tutorial
roscd vis_lecture/xacro/
roslaunch urdf_tutorial display.launch model:=basic2.xacro 

Result

vis_xacro2.png

3.3. Conditions

<!-- vis_lecture/xacro/basic3.xacro -->
<robot name="test_robot" xmlns:xacro="http://ros.org/wiki/xacro">
<!-- Change into red-blue to see color of box change -->
  <xacro:property name="color" value="red" />

  <material name="red">
    <color rgba="1.0 0.0 0.0 2.0"/>
  </material>
  <material name="blue">
    <color rgba="0.0 0.0 1.0 2.0"/>
  </material>

  <link name="base_link">
    <visual>
      <geometry>
        <box size="0.1 0.1 0.1" />
      </geometry>
      <xacro:if value="${color=='red'}">
        <material name="red"/>
      </xacro:if>
      <xacro:if value="${color=='blue'}">
        <material name="blue"/>
      </xacro:if>
    </visual>
  </link>
</robot>

Execute program

# install dependency if needed
# sudo apt install ros-melodic-urdf-tutorial
roscd vis_lecture/xacro/
roslaunch urdf_tutorial display.launch model:=basic3.xacro 

Result is as follow

vis_xacro3.png

Macros

Marcros = function

Source code is as follow

<!-- vis_lecture/xacro/basic4.xacro -->
<robot name="test_robot" xmlns:xacro="http://ros.org/wiki/xacro">
  <material name="red">
    <color rgba="1.0 0.0 0.0 2.0"/>
  </material>
    
  <!-- Defining marcro/function -->
  <xacro:macro name="box_macro" params="suffix parent radius">
    <joint name="${suffix}_joint" type="fixed">
      <origin rpy="0 0 0" xyz="${0.5*cos(radians(radius))} ${0.5*sin(radians(radius))} 0"/>
      <parent link="${parent}"/>
      <child  link="${suffix}_link"/>
    </joint>
    
    <link name="${suffix}_link">
      <visual>
        <geometry>
          <box size="0.1 0.1 0.1" />
        </geometry>
        <material name="red"/>
      </visual>
    </link>
  </xacro:macro>  

  <link name="base_link"/>
  <!-- Calling marcro with parameters = box0, base_link, 0 -->
  <xacro:box_macro suffix="box0" parent="base_link" radius="0"/>
  <!-- Calling marcro with parameters = box1, base_link, 30 -->
  <xacro:box_macro suffix="box1" parent="base_link" radius="30"/>
  <!-- Calling marcro with parameters = box2, base_link, 60 -->
  <xacro:box_macro suffix="box2" parent="base_link" radius="60"/>
  <!-- Calling marcro with parameters = box3, base_link, 90 -->
  <xacro:box_macro suffix="box3" parent="base_link" radius="90"/>
</robot>

Run the code

# install dependency if needed
# sudo apt install ros-melodic-urdf-tutorial
roscd vis_lecture/xacro/
roslaunch urdf_tutorial display.launch model:=basic4.xacro

Output is as follow. We can see that using marcro did shorten urdf a lot.

vis_xacro4.png

Includes

<!-- vis_lecture/xacro/basic5_h.xacro -->
<robot xmlns:xacro="http://ros.org/wiki/xacro">
  <material name="red">
    <color rgba="1.0 0.0 0.0 2.0"/>
  </material>
    
  <xacro:macro name="box_macro" params="suffix parent radius">
    <joint name="${suffix}_joint" type="fixed">
      <origin rpy="0 0 0" xyz="${0.5*cos(radians(radius))} ${0.5*sin(radians(radius))} 0"/>
      <parent link="${parent}"/>
      <child  link="${suffix}_link"/>
    </joint>
    
    <link name="${suffix}_link">
      <visual>
        <geometry>
          <box size="0.1 0.1 0.1" />
        </geometry>
        <material name="red"/>
      </visual>
    </link>
  </xacro:macro>  
</robot>
<!-- vis_lecture/xacro/basic5.xacro -->
<robot name="test_robot" xmlns:xacro="http://ros.org/wiki/xacro">
  <!-- Include basic5_h.xacro -->
  <xacro:include filename="$(find vis_lecture)/xacro/basic5_h.xacro" />

  <link name="base_link"/>
  <xacro:box_macro suffix="box0" parent="base_link" radius="0"/>
  <xacro:box_macro suffix="box1" parent="base_link" radius="30"/>
  <xacro:box_macro suffix="box2" parent="base_link" radius="60"/>
  <xacro:box_macro suffix="box3" parent="base_link" radius="90"/>
</robot>

Run the source code

# install dependency if needed
# sudo apt install ros-melodic-urdf-tutorial
roscd vis_lecture/xacro/
roslaunch urdf_tutorial display.launch model:=basic5.xacro

The output should be as same as “marcro used example”

Launch parameters

<!-- vis_lecture/xacro/basic6.xacro -->
<robot name="test_robot" xmlns:xacro="http://ros.org/wiki/xacro">
  <xacro:arg name="length" default="1.0"/>

  <material name="red">
    <color rgba="1.0 0.0 0.0 2.0"/>
  </material>

  <link name="base_link"/>

  <joint name="body_joint" type="fixed">
    <!-- Launch parameter -->
    <origin rpy="0 0 0" xyz="$(arg length) 0 0"/>
    <parent link="base_link"/>
    <child  link="body_link"/>
  </joint>
  <link name="body_link">
    <visual>
      <geometry>
        <box size="0.1 0.1 0.1" />
      </geometry>
      <material name="red"/>
    </visual>
  </link>
</robot>
<!-- vis_lecture/launch/xacro_expand6.launch -->
<launch>
  <arg name="model" default="$(find vis_lecture)/xacro/basic6.xacro"/>
  <arg name="rvizconfig" default="$(find vis_lecture)/config/xacro_expand.rviz" />
  <arg name="length0" default="1.0" />

  <param name="robot_description" command="$(find xacro)/xacro $(arg model)  length:=$(arg length0) --inorder" />
  <node name="robot_state_publisher" pkg="robot_state_publisher" type="state_publisher" />
  <node name="rviz" pkg="rviz" type="rviz" args="-d $(arg rvizconfig)" required="true" />
</launch>

Execute program

roscd vis_lecture/xacro/
roslaunch vis_lecture xacro_expand6.launch length0:=1.0

The distance between box and (0, 0) should be 1 as follow image

vis_xacro6-0.5.png

The distance will be as follow image

roscd vis_lecture/xacro/
roslaunch vis_lecture xacro_expand6.launch length0:=0.5

vis_xacro6-2.0.png

4. Reference

  1. roswiki: xacro

5. Table of Contents

ROS TOC

Leave a comment