Building an articulated robot arm URDF using Xacro

Our simple robot arm model rrbot consists of three link elements of various heights and two joint elements that join the links together. The joint elements each connect two of the links and enable the links to rotate around one of its axes.

In the next few sections, the rrbot URDF will be created and incrementally built to incorporate the advantages of each of the Xacro features we discussed in the last section. If you have not created the ros_robotics package, refer to the Creating and building a ROS package section in Chapter 2, Creating Your First Two-Wheeled ROS Robot (in Simulation).

Specifying a namespace

In order to create the URDF file from Xacro files, the Xacro file must contain an XML namespace declaration using the xmlns attribute with the xacro tag and corresponding URI. Here is the XML namespace (xmlns) attribute for our rrbot robot arm:

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

This declaration is vital for the file to parse properly. This statement appears as the second line in the main Xacro file, following the XML version reference.

Using the Xacro property tag

For the first iteration of our rrbot robot arm, we will build a URDF file that defines three links with the <visual>, <collision>, and <inertial> tags, and two joints with the <parent>, <child>, <origin>, and <axis> tags. This is a very similar format to the dd_robot URDF file that you are familiar with from Chapter 2, Creating Your First Two-Wheeled ROS Robot (in Simulation). The differences for the Xacro format are listed here and explained in more detail after the code is presented:

  • Addition of the XML namespace declaration on the second line
  • Use of the Xacro <property> tag to define constant values
  • Addition of property names instead of values within the <box> and <origin> tags
  • Simple math (along with property names) to calculate link <origin> z values
  • Joints for this arm are revolute and have the additional tags of <dynamics> and <limit>

The rrbot.xacro file can be downloaded from the Packt website. Otherwise, you can enter the following code into your favorite editor and place the file in your catkin workspace in the ros_robotics package:

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

  <!-- Constants for robot dimensions -->
  <xacro:property name="width" value="0.1" />
  <xacro:property name="height1" value="2" />
  <xacro:property name="height2" value="1" />
  <xacro:property name="height3" value="1" />
  <xacro:property name="axle_offset" value="0.05" />
  <xacro:property name="damp" value="0.7" />

  <!-- Base Link -->
  <link name="base_link">
    <visual>
      <origin xyz="0 0 ${height1/2}" rpy="0 0 0" />
      <geometry>
        <box size="${width} ${width} ${height1}" />
      </geometry>
    </visual>

    <collision>
      <origin xyz="0 0 ${height1/2}" rpy="0 0 0" />
      <geometry>
        <box size="${width} ${width} ${height1}" />
      </geometry>
    </collision>

    <inertial>
      <origin xyz="0 0 ${height1/2}" rpy="0 0 0" />
      <mass value="1" />
      <inertia ixx="1.0" ixy="0.0" ixz="0.0"
               iyy="1.0" iyz="0.0" izz="1.0"/>
    </inertial>
  </link>

  <!-- Joint between Base Link and Middle Link -->
  <joint name="joint_base_mid" type="revolute">
    <parent link="base_link" />
    <child link="mid_link" />
    <origin xyz="0 ${width} ${height1 - axle_offset}" rpy="0 0 0"/>
    <axis xyz="0 1 0"/>
    <dynamics damping="${damp}"/>
    <limit effort="100.0" velocity="0.5" lower="-3.14"
           upper="3.14"/>
  </joint>

  <!-- Middle Link -->
  <link name="mid_link">
    <visual>
      <origin xyz="0 0 ${height2/2 - axle_offset}" rpy="0 0 0" />
      <geometry>
        <box size="${width} ${width} ${height2}" />
      </geometry>
    </visual>

    <collision>
      <origin xyz="0 0 ${height2/2 - axle_offset}" rpy="0 0 0" />
      <geometry>
        <box size="${width} ${width} ${height2}" />
      </geometry>
    </collision>

    <inertial>
      <origin xyz="0 0 ${height2/2 - axle_offset}" rpy="0 0 0" />
      <mass value="1" />
      <inertia ixx="1.0" ixy="0.0" ixz="0.0"
               iyy="1.0" iyz="0.0" izz="1.0" />
    </inertial>
  </link>

  <!-- Joint between Middle Link and Top Link -->
  <joint name="joint_mid_top" type="revolute">
    <parent link="mid_link" />
    <child link="top_link" />
    <origin xyz="0 ${width} ${height2 - axle_offset*2}" rpy="0 00"/>
    <axis xyz="0 1 0" />
    <dynamics damping="${damp}" />
    <limit effort="100.0" velocity="0.5" lower="-3.14"
           upper="3.14"/>
  </joint>

  <!-- Top Link -->
  <link name="top_link">
    <visual>
      <origin xyz="0 0 ${height3/2 - axle_offset}" rpy="0 0 0" />
      <geometry>
        <box size="${width} ${width} ${height3}" />
      </geometry>
    </visual>

    <collision>
      <origin xyz="0 0 ${height3/2 - axle_offset}" rpy="0 0 0" />
      <geometry>
        <box size="${width} ${width} ${height3}" />
      </geometry>
    </collision>

    <inertial>
      <origin xyz="0 0 ${height3/2 - axle_offset}" rpy="0 0 0" />
      <mass value="1" />
      <inertia ixx="1.0" ixy="0.0" ixz="0.0"
               iyy="1.0" iyz="0.0" izz="1.0"/>
    </inertial>
  </link>

</robot>

This file and all the .xacro files should be saved in the /urdf directory of your ros_robotics package.

The preceding XML code defines a robot arm, labeled rrbot, which has three links that are 0.1 meters deep and wide. The base_link link is 2 meters tall, and the mid_link and top_link links are both 1 meter tall. The origin of the base_link is at (0, 0, 1) in order for the arm to be above the ground plane in rviz. The reference frame of the box is 1 meter in the z direction above the reference frame of the link. This base_link is identified as the URDF root link, and is the beginning of the kinematic chain for the arm. The collision elements of each link match their visual elements. Each inertial element indicates that each link weighs 1 kilogram and has the same basic inertia matrix values (we will utilize this duplication of the inertial element when we improve the code for rrbot later in the section Using the Xacro include and macro tags).

In rrbot.xacro, the <property> elements are used for the dimensions of the links, the offset for the axis of rotation, and for the damping coefficient, which are all constant values. These values are declared at the beginning of the XML code, making it easy to change the size of the links, the limits of the joints' rotation, or the damping characteristics of the arm.

Two new tags have been added to the joint elements: <dynamics damping> and <limit>. The dynamics damping coefficient is set to 0.7 Nms/rad. This damping is the amount of opposing force applied to the joint velocity that slows down the moving arms to a rest position. Using the <property> element, this damping value can be changed in one location. You are encouraged to change the value when you run the rrbot URDF/SDF with Gazebo and see the change made to the pendulum's swinging motion. The <limit> tag is required for revolute joints. The limit effort for the maximum joint effort that can be commanded is set to 100.0 N-m. The joint velocity is limited to a magnitude of 0.5 rad/s, with a damping effort applied when the joint is commanded beyond this limit. The upper and lower limits of the joint are set to pi radians and -pi radians, respectively.

Expanding Xacro

To generate a URDF file, the xacro program (from the xacro package) expands all the macros and outputs a resulting URDF file. Make sure that you are in the same directory as the rrbot.xacro file, then run the following command:

$ rosrun xacro xacro --inorder rrbot.xacro > rrbot.urdf

This command will pull together all of the xacro include files, expand the xacro macros in rrbot.xacro, and output the result to rrbot.urdf. The --inorder option mandates that the file be processed in read order. This processing will enable the latest property or macro to overlay a previous definition with the same name. This command is not necessary for running in rviz or Gazebo, but it can be a handy tool when used to examine the full URDF. The URDF XML file is generated with a heading comment warning that the file is autogenerated and that editing the file is not recommended.

The most common way to generate the URDF is in a launch file. The following line of code can be added to a launch file to create the most current robot_description from the Xacro file:

<param name="robot_description"
    command="$(find xacro)/xacro --inorder
      '$(find ros_robotics)/urdf/rrbot.xacro'" />

For complex robots, generating the URDF file at launch time will require a bit more time to process. The advantages are that the URDF is up to date and does not require a lot of memory to be stored.

Using roslaunch for rrbot

Modifications made to the launch file in rviz are necessary, but you will notice similarities to the ddrobot_rviz.launch file in Chapter 2, Creating Your First Two-Wheeled ROS Robot (in Simulation). Either download the rrbot_rviz.launch file from the ros_robotics/launch directory on this book's website, or create the rrbot_rviz.launch file from the following code:

<launch>
  <!-- set parameter on Parameter Server -->
  <arg name="model" />
  <param name="robot_description"
      command="$(find xacro)/xacro --inorder
              '$(find ros_robotics)/urdf/$(arg model)'" />

  <!-- send joint values from gui -->
  <node name="joint_state_publisher" pkg="joint_state_publisher"
        type="joint_state_publisher">
    <param name="use_gui" value="TRUE"/>
  </node>

  <!-- use joint positions to update tf -->
  <node name="robot_state_publisher" pkg="robot_state_publisher"
        type="state_publisher"/>

  <!-- visualize robot model in 3D -->
  <node name="rviz" pkg="rviz" type="rviz"
        args="-d $(find ros_robotics)/urdf.rviz" required="true"/>

</launch>

The main difference in this rviz launch file is the execution of xacro with the argument passed as the model parameter. This process will generate the robot_description parameter to be loaded on the Parameter Server. Make sure that you place this rrbot_rviz.launch file in the /launch directory of your ros_robotics directory.

Note

If you have added the ROS_MASTER_URI and ROS_HOSTNAME or ROS_IP environment variables to your .bashrc file, you will need to comment out these lines with # as the first character of the line. Add the following two commands to your .bashrc file so that you can execute the ROS commands used in this chapter:

export ROS_MASTER_URI=http://localhost:11311//
export ROS_HOSTNAME=localhost

Next, run your rviz roslaunch command:

$ roslaunch ros_robotics rrbot_rviz.launch model:=rrbot.xacro

The rviz screen will look similar to the following screenshot:

Using roslaunch for rrbot

rrbot.xacro in rviz

In the preceding screenshot, notice the pop-up window with two joint control sliders for joint_base_mid and joint_mid_top. The center (0.00) position for both the joints puts the arm in a vertical position. You are encouraged to play with the sliders and the Randomize and Center buttons to understand the controls for the arm joints. The selection of 1 or 2 in the bottom field changes the format of the pop-up window.

Using the Xacro include and macro tags

In the following increment of the rrbot Xacro file, we will use an Xacro <include> tag to specify colors for each link of the robot arm. The materials.xacro file must be in the ros_robotics/urdf directory. To create the materials.xacro file, use the following code:

<?xml version="1.0"?>
<robot>

  <material name="black">
    <color rgba="0.0 0.0 0.0 1.0"/>
  </material>

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

  <material name="green">
    <color rgba="0.0 1.0 0.0 1.0"/>
  </material>

  <material name="grey">
    <color rgba="0.2 0.2 0.2 1.0"/>
  </material>

  <material name="orange">
    <color rgba="${255/255} ${108/255} ${10/255} 1.0"/>
  </material>

  <material name="brown">
    <color rgba="${222/255} ${207/255} ${195/255} 1.0"/>
  </material>

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

  <material name="white">
    <color rgba="1.0 1.0 1.0 1.0"/>
  </material>

</robot>

Color values can be modified to your preferences for colors and textures. Within each <visual> element of the arm link, the following code should be added with any appropriate color:

<material name="any color defined in materials.xacro"/>

An Xacro <macro> block is also added to the rrbot Xacro file to replace the duplicate inertial elements in each link. The macro for <inertial> is as follows:

<xacro:macro name="default_inertial" params="z_value i_value mass">
  <inertial>
    <origin xyz="0 0 ${z_value}" rpy="0 0 0"/>
    <mass value="${mass}" />
    <inertia ixx="${i_value}" ixy="0.0" ixz="0.0"
             iyy="${i_value}" iyz="0.0"izz="${i_value}" />
  </inertial>
</xacro:macro>

Within each <link> of the arm, the entire <inertial> block is replaced with the following code:

<xacro:default_inertial
       z_value="${computation for <origin> in z-axis}"
       i_value="1.0" mass="1"/>

Study the following code to understand the computation for <origin> in the z axis. This code is in the rrbot2.xacro file available for download on this book's website, or can be entered as shown in the following lines (lines from the previous code have been left in or omitted and new code has been highlighted):

<?xml version="1.0"?>
<!-- Revolute-Revolute Manipulator -->
...

  <!-- Import Rviz colors -->
  <xacro:include
         filename="$(find ros_robotics)/urdf/materials.xacro" />

  <!-- Default Inertial -->
  <xacro:macro name="default_inertial" params="z_value i_value mass">
    <inertial>
      <origin xyz="0 0 ${z_value}" rpy="0 0 0"/>
      <mass value="${mass}" />
      <inertia ixx="${i_value}" ixy="0.0" ixz="0.0"
              iyy="${i_value}" iyz="0.0"
              izz="${i_value}" />
    </inertial>
  </xacro:macro>

  <!-- Base Link -->
  ...
    </collision>

    <xacro:default_inertial z_value="${height1/2}"
                             i_value="1.0" mass="1"/>
  </link>
  ...
  <!-- Middle Link -->
  ...
    </collision>

    <xacro:default_inertial z_value="${height2/2 - axle_offset}"
                             i_value="1.0" mass="1"/>
  </link>
  ...
  <!-- Top Link -->
  ...
    </collision>

    <xacro:default_inertial z_value="${height3/2 - axle_offset}"
                            i_value="1.0" mass="1"/>
  </link>

</robot>

Next, run the rviz roslaunch command:

$ roslaunch ros_robotics rrbot_rviz.launch model:=rrbot2.xacro

The rviz screen will look similar to the following screenshot:

Using the Xacro include and macro tags

rrbot2.xacro in rviz

Although the book may show the screenshot in shades of gray, the base_link of the arm is now red, the mid_link is green, and the top_link is blue. On your screen, you will see the colors specified in your rrbot2.xacro file. The arm is shown in a random pose.

Adding mesh to the robot arm

A mesh is a collection of polygonal surfaces that provides a more realistic shape for an object in 3D. Although adding a mesh to the URDF is not unique to Xacro, we include the exercise here to give you the experience of using meshes and to append a more realistic gripper to our robot arm.

For the next upgrade to our robot arm, we will add a composite mesh image of a gripper to the top_link of the arm. To make our code design modular, we will create the gripper code in a separate file and use an Xacro <include> statement in the main rrbot3.xacro file:

<xacro:include filename="$(find ros_robotics)/urdf/gripper.xacro" />

Using this <include> statement, the gripper.xacro file must be in the ros_robotics/urdf directory.

The gripper is defined as four links with the <visual>, <collision>, and <inertial> tags, and four joints with the <parent>, <child>, <origin>, and <axis> tags. The four links are identified as left_gripper, left_tip, right_gripper, and right_tip. The links utilize the mesh files from the PR2 robot for their <visual> and <geometry> definitions. The PR2 robot is another famous Willow Garage robot, now mainly used for academic research. The pr2_description Xacro files are part of the ros-kinetic-desktop-full installation described in the Installing and launching ROS section in Chapter 1, Getting Started with ROS. The files used for the gripper are found in the /opt/ros/kinetic/share/pr2_description/meshes/gripper_v0 directory. The l_finger.dae and l_finger_tip.dae files should be copied to a /meshes directory under your ros_robotics package directory, or they can be downloaded from the example code on this book's website.

The code to add the mesh file to the left_gripper link:

<link name="left_gripper">
  <visual>
    <origin xyz="0 0 0" rpy="0 0 0"/>
    <geometry>
      <mesh
          filename="package://ros_robotics/meshes/l_finger.dae"/>
    </geometry>
  </visual>

The other links follow the same format with the left_tip and right_tip links both utilizing the l_finger_tip.dae file. The .dae file is a Digital Asset Exchange file in the COLLADA format, representing a 3D image. These images can be created in Photoshop, SketchUp, AutoCAD, Blender, and other graphics software.

You can use the same geometry or meshes for both the <collision> and <visual> elements, although for performance improvements, we strongly suggest that you have simplified models/meshes for your collision geometry. A good open-source tool used to simplify meshes is Blender. There are many closed-source tools, such as Maya and 3DS Max, that can also simplify meshes. In the case of our robot arm, we specify simple rectangular shapes to be <collision><geometry> for each of these links.

Two types of joints are used for our gripper. The left_gripper and right_gripper links are connected to top_link of our robot arm using a revolute joint to restrict the range of movement of the joint. A <limit> tag is required for a revolute joint to define the <effort>, <velocity>, <lower>, and <upper> limits of the range. The effort limit is set to 30 Nm, the velocity limit is 0.1 rad/s, and the range is from -0.548 to 0.0 radians for the left_gripper_joint and right_gripper_joint.

A fixed joint is specified between the left_gripper and the left_tip and also between the right_gripper and the right_tip. There is no movement between these links.

This following code is provided for gripper.xacro, or it can be downloaded from the Packt website for this book:

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

  <!-- Gripper -->
  <joint name="left_gripper_joint" type="revolute">
    <parent link="top_link"/>
    <child link="left_gripper"/>
    <origin xyz="0 0 ${height2 - axle_offset}" rpy="0 -1.57 0"/>
    <axis xyz="0 0 -1"/>
    <limit effort="30.0" lower="-0.548" upper="0.0" velocity="0.1"/>
  </joint>

  <link name="left_gripper">
    <visual>
      <origin xyz="0 0 0" rpy="0 0 0"/>
      <geometry>
        <mesh
           filename="package://ros_robotics/meshes/l_finger.dae"/>
      </geometry>
    </visual>

    <collision>
      <origin xyz="0.05 0.025 0" rpy="0 0 0"/>
      <geometry>
        <box size="0.1 0.05 0.05"/>
      </geometry>
    </collision>
    <xacro:default_inertial z_value="0" i_value="1e-6" mass="1"/>
  </link>

  <joint name="left_tip_joint" type="fixed">
    <parent link="left_gripper"/>
    <child link="left_tip"/>
  </joint>

  <link name="left_tip">
    <visual>
      <origin xyz="0.09137 0.00495 0" rpy="0 0 0"/>
      <geometry>
        <mesh
       filename="package://ros_robotics/meshes/l_finger_tip.dae"/>
      </geometry>
    </visual>

    <collision>
      <origin xyz="0.11 0.005 0"rpy="0 0 0"/>
      <geometry>
        <box size="0.02 0.03 0.02"/>
      </geometry>
    </collision>
    <xacro:default_inertial z_value="0" i_value="1e-6"
                            mass="1e-5"/>
  </link>

  <joint name="right_gripper_joint" type="revolute">
    <parent link="top_link"/>
    <child link="right_gripper"/>
    <origin xyz="0 0 ${height2 - axle_offset}" rpy="0 -1.57 0"/>
    <axis xyz="0 0 1"/>
    <limit effort="30.0" lower="-0.548" upper="0.0" velocity="0.1"/>
  </joint>

  <link name="right_gripper">
    <visual>
      <origin xyz="0 0 0" rpy="3.1415 0 0"/>
      <geometry>
        <mesh
           filename="package://ros_robotics/meshes/l_finger.dae"/>
      </geometry>
    </visual>

    <collision>
      <origin xyz="0.05 -0.025 0" rpy="0 0 0"/>
      <geometry>
        <box size="0.1 0.05 0.05"/>
      </geometry>
    </collision>
    <xacro:default_inertial z_value="0" i_value="1e-6" mass="1"/>
  </link>

  <joint name="right_tip_joint" type="fixed">
    <parent link="right_gripper"/>
    <child link="right_tip"/>
  </joint>

  <link name="right_tip">
    <visual>
      <origin xyz="0.09137 0.00495 0" rpy="-3.1415 0 0"/>
      <geometry>
        <mesh
       filename="package://ros_robotics/meshes/l_finger_tip.dae"/>
      </geometry>
    </visual>

    <collision>
      <origin xyz="0.11 -0.005 0" rpy="0 0 0"/>
      <geometry>
        <box size="0.02 0.03 0.02"/>
      </geometry>
    </collision>
    <xacro:default_inertial z_value="0" i_value="1e-6"
                mass="1e-5"/>
  </link>
</robot>

Next, run the rviz roslaunch command:

$ roslaunch ros_robotics rrbot_rviz.launch model:=rrbot3.xacro

Note

Note that a number of warning messages similar to TIFFFieldWithTag: Internal error, unknown tag xxxxxx may be displayed. This message is not an indication of any operational problem, and you may continue without difficulty.

A close-up view of the gripper should look similar to the following screenshot:

Adding mesh to the robot arm

rrbot gripper in rviz

The controls for the arm and gripper are accessible via the four joint control sliders, as shown in the following screenshot. Controls for left_gripper_joint and right_gripper_joint have been added to the arm joints. The robot arm is shown in a random pose:

Adding mesh to the robot arm

rrbot3.xacro in rviz

With our robot arm built using Xacro, we are ready to add modifications to the Xacro file so that it can be recognized as an SDF by Gazebo. Then, we will add transmission and control plugins to enable our robot arm to be controlled by ROS commands from the command line or rqt.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.116.40.53