ROS course 68: using xarco part 1
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)
- Property and property blocks : use to create and set variable
- Mathemetics
- Conditions
- Macros : very useful when statements are repeated or reused with modification defined by parameters
- Can use rospack
- 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
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
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
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.
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
The distance will be as follow image
roscd vis_lecture/xacro/
roslaunch vis_lecture xacro_expand6.launch length0:=0.5
Leave a comment